Содержание
- Исключения
- Несколько исключений
- Вложенные операторы try
- Оператор throw
- Оператор throws
- Оператор finally
- Встроенные исключения Java
- Создание собственных классов исключений
- Перехват произвольных исключений
- Основные правила обработки исключений
Исключения
Исключение — это нештатная ситуация, ошибка во время выполнения программы. Самый простой пример — деление на ноль. Можно вручную отслеживать возникновение подобных ошибок, а можно воспользоваться специальным механизмом исключений, который упрощает создание больших надёжных программ, уменьшает объём необходимого кода и повышает уверенность в том, что в приложении не будет необработанной ошибки.
В методе, в котором происходит ошибка, создаётся и передаётся специальный объект. Метод может либо обработать исключение самостоятельно, либо пропустить его. В любом случае исключение ловится и обрабатывается. Исключение может появиться благодаря самой системе, либо вы сами можете создать его вручную. Системные исключения возникают при неправильном использовании языка Java или запрещённых приёмов доступа к системе. Ваши собственные исключения обрабатывают специфические ошибки вашей программы.
Вернёмся к примеру с делением. Деление на нуль может предотвратить проверкой соответствующего условия. Но что делать, если знаменатель оказался нулём? Возможно, в контексте вашей задачи известно, как следует поступить в такой ситуации. Но, если нулевой знаменатель возник неожиданно, деление в принципе невозможно, и тогда необходимо возбудить исключение, а не продолжать исполнение программы.
Существует пять ключевых слов, используемых в исключениях: try, catch, throw, throws, finally. Порядок обработки исключений следующий.
Операторы программы, которые вы хотите отслеживать, помещаются в блок try. Если исключение произошло, то оно создаётся и передаётся дальше. Ваш код может перехватить исключение при помощи блока catch и обработать его. Системные исключения автоматически передаются самой системой. Чтобы передать исключение вручную, используется throw. Любое исключение, созданное и передаваемое внутри метода, должно быть указано в его интерфейсе ключевым словом throws. Любой код, который следует выполнить обязательно после завершения блока try, помещается в блок finally
Схематически код выглядит так:
Существует специальный класс для исключений Trowable. В него входят два класса Exception и Error.
Класс Exception используется для обработки исключений вашей программой. Вы можете наследоваться от него для создания собственных типов исключений. Для распространённых ошибок уже существует класс RuntimeException, который может обрабатывать деление на ноль или определять ошибочную индексацию массива.
Класс Error служит для обработки ошибок в самом языке Java и на практике вам не придётся иметь с ним дело.
Прежде чем научиться обрабатывать исключения, нам (как и нормальному любопытному коту) хочется посмотреть, а что происходит, если ошибку не обработать. Давайте разделим число котов в вашей квартире на ноль, хотя мы и знаем, что котов на ноль делить нельзя!
Я поместил код в обработчик щелчка кнопки. Когда система времени выполнения Java обнаруживает попытку деления на ноль, она создаёт объект исключения и передаёт его. Да вот незадача, никто не перехватывает его, хотя это должны были сделать вы. Видя вашу бездеятельность, объект перехватывает стандартный системный обработчик Java, который отличается вредных характером. Он останавливает вашу программу и выводит сообщение об ошибке, которое можно увидеть в журнале LogCat:
Как видно, созданный объект исключения принадлежит к классу ArithmeticException, далее системный обработчик любезно вывел краткое описание ошибки и место возникновения.
Вряд ли пользователи вашей программы будут довольны, если вы так и оставите обработку ошибки системе. Если программа будет завершаться с такой ошибкой, то скорее всего вашу программу просто удалят. Посмотрим, как мы можем исправить ситуацию.
Поместим проблемный код в блок try, а в блоке catch обработаем исключение.
Теперь программа аварийно не закрывается, так как мы обрабатываем ситуацию с делением на ноль.
В данном случае мы уже знали, к какому классу принадлежит получаемая ошибка, поэтому в блоке catch сразу указали конкретный тип. Обратите внимание, что последний оператор в блоке try не срабатывает, так как ошибка происходит раньше строчкой выше. Далее выполнение передаётся в блок catch, далее выполняются следующие операторы в обычном порядке.
Операторы try и catch работают совместно в паре. Хотя возможны ситуации, когда catch может обрабатывать несколько вложенных операторов try.
Если вы хотите увидеть описание ошибки, то параметр e и поможет увидеть ёго.
По умолчанию, класс Trowable, к которому относится ArithmeticException возвращает строку, содержащую описание исключения. Но вы можете и явно указать метод e.toString.
Несколько исключений
Фрагмент кода может содержать несколько проблемных мест. Например, кроме деления на ноль, возможна ошибка индексации массива. В таком случае вам нужно создать два или более операторов catch для каждого типа исключения. Причём они проверяются по порядку. Если исключение будет обнаружено у первого блока обработки, то он будет выполнен, а остальные проверки пропускаются и выполнение программы продолжается с места, который следует за блоком try/catch.
В примере мы добавили массив с тремя элементами, но обращаемся к четвёртому элементу, так как забыли, что отсчёт у массива начинается с нуля. Если оставить значение переменной zero равным нулю, то сработает обработка первого исключения деления на ноль, и мы даже не узнаем о существовании второй ошибки. Но допустим, что в результате каких-то вычислений значение переменной стало равно единице. Тогда наше исключение ArithmeticException не сработает. Но сработает новое добавленное исключение ArrayIndexOutOfBoundsException. А дальше всё пойдёт как раньше.
Тут всегда нужно помнить одну особенность. При использовании множественных операторов catch обработчики подклассов исключений должные находиться выше, чем обработчики их суперклассов. Иначе, суперкласс будет перехватывать все исключения, имея большую область перехвата. Иными словами, Exception не должен находиться выше ArithmeticException и ArrayIndexOutOfBoundsException. К счастью, среда разработки сама замечает непорядок и предупреждает вас, что такой порядок не годится. Увидев такую ошибку, попробуйте перенести блок обработки исключений ниже.
Вложенные операторы try
Операторы try могут быть вложенными. Если вложенный оператор try не имеет своего обработчика catch для определения исключения, то идёт поиск обработчика catch у внешнего блока try и т.д. Если подходящий catch не будет найден, то исключение обработает сама система (что никуда не годится).
Оператор throw
Часть исключений может обрабатывать сама система. Но можно создать собственные исключения при помощи оператора throw. Код выглядит так:
Вам нужно создать экземпляр класса Throwable или его наследников. Получить объект класса Throwable можно в операторе catch или стандартным способом через оператор new.
Мы могли бы написать такой код для кнопки:
Мы объявили объект класса Cat, но забыли его проинициализировать, например, в onCreate(). Теперь нажатие кнопки вызовет исключение, которое обработает система, а в логах мы можем прочитать сообщение об ошибке. Возможно, вы захотите использовать другое исключение, например, throw new UnsupportedOperationException(«Котик не инициализирован»);.
В любом случае мы передали обработку ошибки системе. В реальном приложении вам нужно обработать ошибку самостоятельно.
Поток выполнения останавливается непосредственно после оператора throw и другие операторы не выполняются. При этом ищется ближайший блок try/catch соответствующего исключению типа.
Перепишем пример с обработкой ошибки.
Мы создали новый объект класса NullPointerException. Многие классы исключений кроме стандартного конструктора по умолчанию с пустыми скобками имеют второй конструктор с строковым параметром, в котором можно разместить подходящую информацию об исключении. Получить текст из него можно через метод getMessage(), что мы и сделали в блоке catch.
Теперь программа не закроется аварийно, а будет просто выводить сообщения в всплывающих Toast.
Оператор throws
Если метод может породить исключение, которое он сам не обрабатывает, он должен задать это поведение так, чтобы вызывающий его код мог позаботиться об этом исключении. Для этого к объявлению метода добавляется конструкция throws, которая перечисляет типы исключений (кроме исключений Error и RuntimeException и их подклассов).
Общая форма объявления метода с оператором throws:
В фрагменте список_исключений можно указать список исключений через запятую.
Создадим метод, который может породить исключение, но не обрабатывает его. А в щелчке кнопки вызовем его.
Если вы запустите пример, то получите ошибку. Исправим код.
Мы поместили вызов метода в блок try и вызвали блок catch с нужным типом исключения. Теперь ошибки не будет.
Оператор finally
Когда исключение передано, выполнение метода направляется по нелинейному пути. Это может стать источником проблем. Например, при входе метод открывает файл и закрывает при выходе. Чтобы закрытие файла не было пропущено из-за обработки исключения, был предложен механизм finally.
Ключевое слово finally создаёт блок кода, который будет выполнен после завершения блока try/catch, но перед кодом, следующим за ним. Блок будет выполнен, независимо от того, передано исключение или нет. Оператор finally не обязателен, однако каждый оператор try требует наличия либо catch, либо finally.
Встроенные исключения Java
Существуют несколько готовых системных исключений. Большинство из них являются подклассами типа RuntimeException и их не нужно включать в список throws. Вот небольшой список непроверяемых исключений.
- ArithmeticException — арифметическая ошибка, например, деление на нуль
- ArrayIndexOutOfBoundsException — выход индекса за границу массива
- ArrayStoreException — присваивание элементу массива объекта несовместимого типа
- ClassCastException — неверное приведение
- EnumConstantNotPresentException — попытка использования неопределённого значения перечисления
- IllegalArgumentException — неверный аргумент при вызове метода
- IllegalMonitorStateException — неверная операция мониторинга
- IllegalStateException — некорректное состояние приложения
- IllegalThreadStateException — запрашиваемая операция несовместима с текущим потоком
- IndexOutofBoundsException — тип индекса вышел за допустимые пределы
- NegativeArraySizeException — создан массив отрицательного размера
- NullPointerException — неверное использование пустой ссылки
- NumberFormatException — неверное преобразование строки в числовой формат
- SecurityException — попытка нарушения безопасности
- StringIndexOutOfBounds — попытка использования индекса за пределами строки
- TypeNotPresentException — тип не найден
- UnsupportedOperationException — обнаружена неподдерживаемая операция
Список проверяемых системных исключений, которые можно включать в список throws.
- ClassNotFoundException — класс не найден
- CloneNotSupportedException — попытка клонировать объект, который не реализует интерфейс Cloneable
- IllegalAccessException — запрещен доступ к классу
- InstantiationException — попытка создать объект абстрактного класса или интерфейса
- InterruptedException — поток прерван другим потоком
- NoSuchFieldException — запрашиваемое поле не существует
- NoSuchMethodException — запрашиваемый метод не существует
- ReflectiveOperationException — исключение, связанное с рефлексией
Создание собственных классов исключений
Система не может предусмотреть все исключения, иногда вам придётся создать собственный тип исключения для вашего приложения. Вам нужно наследоваться от Exception (напомню, что этот класс наследуется от Trowable) и переопределить нужные методы класса Throwable. Либо вы можете наследоваться от уже существующего типа, который наиболее близок по логике с вашим исключением.
- final void addSuppressed(Throwable exception) — добавляет исключение в список подавляемых исключений (JDK 7)
- Throwable fillInStackTrace() — возвращает объект класса Throwable, содержащий полную трассировку стека.
- Throwable getCause() — возвращает исключение, лежащее под текущим исключение или null
- String getLocalizedMessage() — возвращает локализованное описание исключения
- String getMessage() — возвращает описание исключения
- StackTraceElement[] getStackTrace() — возвращает массив, содержащий трассировку стека и состояний из элементов класса StackTraceElement
- final Throwable[] getSuppressed() — получает подавленные исключения (JDK 7)
- Throwable initCause(Throwable exception) — ассоциирует исключение с вызывающим исключением. Возвращает ссылку на исключение.
- void printStackTrace() — отображает трассировку стека
- void printStackTrace(PrintStream stream) — посылает трассировку стека в заданный поток
- void printStackTrace(PrintWriter stream) — посылает трассировку стека в заданный поток
- void setStackTrace(StackTraceElement elements[]) — устанавливает трассировку стека для элементов (для специализированных приложений)
- String toString() — возвращает объект класса String, содержащий описание исключения.
Самый простой способ — создать класс с конструктором по умолчанию.
Мы создали собственный класс HungryCatException, в методе testMethod() его возбуждаем, а по нажатию кнопки вызываем этот метод. В результате наше исключение сработает.
Создать класс исключения с конструктором, который получает аргумент-строку, также просто.
Ещё вариант. Добавим также метод toString().
Теперь класс содержит два конструктора. Во втором конструкторе используется конструктор родительского класса с аргументом String, вызываемый ключевым словом super.
Перехват произвольных исключений
Можно создать универсальный обработчик, перехватывающий любые типы исключения. Осуществляется это перехватом базового класса всех исключений Exception:
Подобная конструкция не упустит ни одного исключения, поэтому её следует размещать в самом конце списка обработчиков, во избежание блокировки следующих за ней обработчиков исключений.
Основные правила обработки исключений
Используйте исключения для того, чтобы:
- обработать ошибку на текущем уровне (избегайте перехватывать исключения, если не знаете, как с ними поступить)
- исправить проблему и снова вызвать метод, возбудивший исключение
- предпринять все необходимые действия и продолжить выполнение без повторного вызова действия
- попытаться найти альтернативный результат вместо того, который должен был бы произвести вызванный метод
- сделать все возможное в текущем контексте и заново возбудить это же исключение, перенаправив его на более высокий уровень
- сделать все, что можно в текущем контексте, и возбудить новое исключение, перенаправив его на более высокий уровень
- завершить работу программы
- упростить программу (если используемая схема обработки исключений делает все только сложнее, значит, она никуда не годится)
- добавить вашей библиотеке и программе безопасности
Источник
Классы исключений
Последнее обновление: 23.04.2018

Базовым классом для всех исключений является класс Throwable. От него уже наследуются два класса: Error
и Exception. Все остальные классы являются производными от этих двух классов.
Класс Error описывает внутренние ошибки в исполняющей среде Java. Программист имеет очень ограниченные возможности для обработки подобных ошибок.
Собственно исключения наследуются от класса Exception. Среди этих исключений следует выделить класс RuntimeException.
RuntimeException является базовым классом для так называемой группы непроверяемых исключений (unchecked exceptions) —
компилятор не проверяет факт обработки таких исключений и их можно не указывать вместе с оператором throws в объявлении метода.
Такие исключения являются следствием ошибок разработчика, например, неверное преобразование типов или выход за пределы массива.
Некоторые из классов непроверяемых исключений:
-
ArithmeticException: исключение, возникающее при делении на ноль
-
IndexOutOfBoundException: индекс вне границ массива
-
IllegalArgumentException: использование неверного аргумента при вызове метода
-
NullPointerException: использование пустой ссылки
-
NumberFormatException: ошибка преобразования строки в число
Все остальные классы, образованные от класса Exception, называются проверяемыми исключениями (checked exceptions).
Некоторые из классов проверяемых исключений:
-
CloneNotSupportedException: класс, для объекта которого вызывается клонирование, не реализует интерфейс Cloneable
-
InterruptedException: поток прерван другим потоком
-
ClassNotFoundException: невозможно найти класс
Подобные исключения обрабатываются с помощью конструкции try..catch. Либо можно передать обработку методу, который будет вызывать данный метод,
указав исключения после оператора throws:
public Person clone() throws CloneNotSupportedException{
Person p = (Person) super.clone();
return p;
}
В итоге получается следующая иерархия исключений:
Поскольку все классы исключений наследуются от класса Exception, то все они наследуют ряд его методов, которые позволяют получить информацию о
характере исключения. Среди этих методов отметим наиболее важные:
-
Метод getMessage() возвращает сообщение об исключении
-
Метод getStackTrace() возвращает массив, содержащий трассировку стека исключения
-
Метод printStackTrace() отображает трассировку стека
Например:
try{
int x = 6/0;
}
catch(Exception ex){
ex.printStackTrace();
}
4. Обработка ошибок, исключения, отладка
4.1. Исключения
Примеры работы с ошибками
public interface Calculator { double calculate(String expr); }
- Самый простой способ обработать ошибочное значение в методе — завершить исполнение с
System.exit(1) - Лучший способ возвращать специальное значение, например
Double.NAN. - Можно также завести поле под признак ошибки внутри класса
Примеры исключений
Object nullRef = null;
// java.lang.NullPointerException
nullRef.toString();
int[] array = {1, 2, 3};
// java.lang.ArrayIndexOutOfBoundsException
array[10];
// java.io.FileNotFoundException
new FileInputStream("not_existing_file");
java.lang.Throwable
Все исключения в Java наследуются от java.lang.Throwable
throw new IllegalStateException("Invalid user.");
Методы Throwable
public String getMessage()получить строку из конструктора исключенияpublic void printStackTrace()печатает stacktrace в stderrpublic StackTraceElement[] getStackTrace()возвращает stacktrace в виде массиваpublic Throwable getCause()— возвращает другое исключение, явившееся причиной данного илиnull, если данное исключение является первичным. Причина может быть задана при инициализации исключенияpublic Trowable[] getSuppressed()— возвращает исключения, которые были заглушены в процессе обработки основного исключения
Классификация исключений
- Исключительные ситуации в JVM —
java.lang.Error - Исключительные ситуации в пользовательском коде
- Проверяемые (checked) —
java.lang.Exception - Непроверяемые (unchecked) —
java.lang.RuntimeException, наследуетjava.lang.Exception
- Проверяемые (checked) —
java.lang.Error
java.lang.OutOfMemoryErrorjava.lang.NoClassFoundErrorjava.lang.VeirfyError
java.lang.Exception
import java.io.IOException; public class ExceptionDemo { public void someMethod() throws IOException { throw new IOException("Failed to read file."); } }
java.lang.RuntimeException
java.lang.NullPointerExceptionjava.lang.ArrayIndexOufOfBoundExceptionjava.lang.ArithmeticException
Собственное исключение
public class CalculatorException extends RuntimeException { public CalculatorException(String message) { super(message); } public CalculatorException(String message, Throwable cause) { super(message, cause); } }
4.2. Обработка исключений. Try-catch
Базовый пример
for (;;) {
System.out.print("Enter expression: ");
String expression = readUserInput();
if (expr == null || "exit".equalsIgnoreCase(expr)) {
break;
}
try {
double result = calculator.calculat(expr);
System.out.println("Result: " + result);
} catch (CalculatorException e) {
System.out.print("Bad expression: " + e.getMessage());
System.out.print("Please try again: ");
}
}
Перехват нескольких исключений
try {
// ...
} catch (FirstException e) {
e.printStackTrace();
} catch (SecondException e) {
e.printStackTrace();
}
или в одном блоке catch
try {
// ...
} catch (FirstException | SecondException e) {
e.printStackTrace();
}
Блок finally
InputStream is = new FileInputStream("a.txt");
try {
readFromInputStream(is);
} finally {
is.close();
}
finally обрабатывает всегда вне зависимости от вызванных исключений. Обычно предназначен для снятия блокировок, закрытия ресурсов.
В примере выше, если исключение будет брошено внутри try и внутри finally, то оригинальное исключение будет потеряно. Для решения этой проблемы используется следующий паттерн
InputStream is = new FileInputStream("a.txt");
try {
readFromInputStream(is);
} finally {
try {
is.close();
} catch (IOException e) {
// ignore
}
}
try с ресурсами
try (InputStream is = new FileInputStream("a.txt")) {
readFromInputStream(is);
}
- Несколько ресурсов перечисляется через
; - При выходе из блока все ресурсы будут освобождены (вызван метод
close()) - Исключение из
close()не перебьет первое, а будет добавлено как заглушенное
Идея за реализацией try с ресурсами
InputStream is = new FileInputStream("a.txt");
try {
readFromInputStream(is);
} catch (Throwable t) {
try {
is.close();
} catch (Trhowable t2) {
t.addSuppressed(t2);
}
throw t;
}
is.close();
Ресурс
Ресурс — любой объект реализующий java.lang.AutoCloseable.
package java.lang;
public static AutoClosable {
void close() throws Exception;
}
Обработка исключения
try {
Double.parseDouble(...);
} catch (NumberFormatException e) {
throw new CalculatorException(e);
}
Для простого логирования ошибки: e.printStackTrace().
Плохой пример
String string;
try {
string = object.toString();
} catch (NullPointerException e) {
string = "null";
}
System.out.println(string);
Хороший пример
String string = object == null ? "null" : object.toString();
System.out.println(string);
Можно также воспользоваться Objects.toString(object) из java.util, который реализует туже логику.
4.3. Логирование
Пример
package org.stepik.java.logging;
import java.util.logging.*;
public class LogDemo {
private static final Logger LOGGER = Logger.getLogger(LogDemo.class.getName());
}
Логирование сообщений
LOGGER.log(Level.INFO, "I'm logging");
// SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST
LOGGER.warning("We have a problem!);
Настройка уровня логирования
LOGGER.setLevel(Level.WARNING);
Добавление в сообщение дополнительной информации
LOGGER.log(Level.FINEST, "Current value of x is " + x);
LOGGER.log(Level.FINEST, "Current value of x is {0}", x);
LOGGER.log(Level.FINEST, "Point coordinates are ({0}, {1})", new Object[] {x, y});
LOGGER.log(Level.SEVERE, "Unexpected exception", e);
Обработчики сообщений
Определяют куда будет записано сообщение.
java.util.logging.ConsoleHandlerjava.util.logging.FileHandlerjava.util.logging.SocketHandler
Форматеры сообщений
Определяют формат вывода.
java.util.logging.SimpleFormatterjava.util.logging.XMLFormatter
Полный пример
Logger logger = Logger.getLogger(Stepik.class.getName());
Handler handler;
try {
handler = new FileHandler("log.xml");
} catch (Exception e) {
handler = new ConsoleHandler();
}
Formatter formatter = new XMLFormatter();
handler.setFormatter(formatter);
handler.setLevel(Level.WARNING);
logger.addHandler(handler);
logger.log(Level.INFO, "test info");
logger.log(Level.WARNING, "test warning"); // Выводится в файл
Классы Java для обработки исключительных ситуаций из пакета java.lang. Методы класса Throwable. Примеры
Содержание
- 1. Типы исключений, которые поддерживаются системой обработки исключений Java
- 2. Классификация исключений по признаку наличия в операторе throws. Непроверяемые исключения. Проверяемые исключения
- 3. Перечень подклассов непроверяемых исключений из пакета java.lang
- 4. Проверяемые исключения из пакета java.lang
- 5. Какое назначение класса Throwable? Методы класса Throwable
- 6. Пример использования некоторых методов класса Throwable. Разработка собственного класса исключения
- Связанные темы
Поиск на других ресурсах:
1. Типы исключений, которые поддерживаются системой обработки исключений Java
В языке программирования Java разработан эффективный механизм обработки исключений. В основе этого механизма лежат классы образующие иерархию. Для всех классов исключений Java базовым классом есть класс Throwable.
Из класса Throwable унаследованы два основных класса:
- Exception – предназначен для задания исключительных условий, которые перехватываются программой. Если нужно объявить собственный класс (тип) исключений, то этот класс может быть унаследован от класса Exception;
- Error – класс, который предназначен для описания исключений (ошибок) возникающих в самой среде Java. Такие исключения не оговариваются во время нормального выполнения прикладной программы. Примеры системных ошибок: недостаточно памяти, переполнение стека.
Схема верхнего уровня иерархии классов Java приведена на рисунке
Рисунок. Вершина иерархии классов исключений Java
⇑
2. Классификация исключений по признаку наличия в операторе throws. Непроверяемые исключения. Проверяемые исключения
Как известно, метод может генерировать исключения, которые могут быть перехвачены в других методах высших уровней. При этом, метод должен указывать перечень обрабатываемых исключений в операторе throws.
Более подробно о работе оператора throws описывается в теме:
- Операторы throw, throws. Примеры
Если тип сгенерированного исключения есть подклассом стандартного класса RuntimeException, то не обязательно указывать этот тип в перечне оператора throws метода. Такое исключение называется непроверяемым исключением. В этом случае компилятор не проверяет обрабатываются или генерируются такие исключения в некотором месте программы.
Если тип сгенерированного исключения не является подклассом стандартного класса RuntimeException, то это исключение называется проверяемое исключение. В случае генерирования такого типа исключения, его нужно обязательно включать в оператор throws.
⇑
3. Перечень подклассов непроверяемых исключений из пакета java.lang
Среди всего разнообразия классов и интерфейсов пакет java.lang содержит мощный арсенал классов для обработки исключений. Эти классы и интерфейсы составляют основу всех программ на Java. Пакет java.lang автоматически импортируется во все программы.
Ниже приведен перечень подклассов непроверяемых исключений производными от класса RuntimeException и которые определены в пакете java.lang:
- ArithmeticException – арифметическая ошибка (например, деление на ноль);
- ArrayIndexOutOfBoundsException – индекс за пределами массива;
- ArrayStoreException – присваивание элементу массива объекта несовместимого типа;
- ClassCastException – неправильное приведение типов;
- EnumConstantNotPresent – попытка воспользоваться неопределенным значением перечисления;
- IllegalArgumentException – недопустимый аргумент при вызове метода;
- IllegalMonitorStateException – недопустимая контрольная операция;
- IllegalStateException – неверное состояние среды или приложения;
- IllegalThreadStateException – несовместимость запрашиваемой операции с текущим состоянием потока выполнения;
- IndexOutOfBoundsException – выход индекса некоторого типа за допустимые границы;
- NegativeArraySizeException – создание массива отрицательного размера;
- NullPointerException – неправильное использование пустой ссылки;
- NumberFormatException – неправильное преобразование символьной строки в числовой формат;
- SecurityException – попытка нарушения безопасности;
- StringIndexOutOfBounds – попытка доступа по индексу за пределами символьной строки;
- TypeNotPresentException – тип не найден;
- UnsupportedOperationException – найдена неподдерживаемая операция.
⇑
4. Проверяемые исключения из пакета java.lang
Если тип сгенерированного исключения не является подклассом стандартного класса RuntimeException, то это исключение называется проверяемым исключением. В случае генерирования такого типа исключения, его обязательно нужно включать в оператор throws метода.
В языке Java в пакете java.lang реализован ряд проверяемых исключений. Ниже приведен их перечень:
- ClassNotFoundException – класс не найден;
- CloneNotSupportedException – попытка клонировать объект из класса, который не реализует интерфейс Cloneable;
- IllegalAccessException – запрещен доступ к классу;
- InstantiationException – попытка создать объект абстрактного класса или интерфейса;
- InterruptedException – один поток выполнения прерван другим потоком;
- NoSuchFieldException – запрашиваемое поле не существует;
- NoSuchMethodException – запрашиваемый метод не существует;
- ReflectiveOperationException – суперкласс исключений, связанных с рефлексией.
Также, в перечень исключений оператора throws обязательно нужно включать собственноручно разработанные классы исключений для их проверки.
⇑
5. Какое назначение класса Throwable? Методы класса Throwable
Класс Throwable есть базовым для всех стандартных классов исключений Java. Этот класс предоставляет ряд методов, которые можно использовать или переопределять в собственных классах обработки исключений. Эти классы должны быть унаследованы от класса Exception, который унаследован от класса Throwable (см. рисунок). Класс Exception не содержит методов.
Ниже приведен перечень методов класса Throwable.
1. Метод
final void addSuppressed(Throwable исключение)
добавляет заданное исключение в список подавляемых исключений. Этот список связывается с вызывающим (данным) исключением. Метод используется для применения в операторе try с ресурсами.
2. Метод
Throwable fillInStackTrace()
возвращает объект класса Throwable, содержащий полную трассировку стека. Этот объект может быть сгенерирован повторно.
3. Метод
Throwable getCause()
возвращает исключение, лежащее в основе текущего исключения. Метод возвращает null в случае, если такое исключение отсутствует. Этот метод используется при создании цепочек исключений – он вызывает исключение, вызывающее текущее исключение.
4. Метод
String getLocalizedMessage()
возвращает локализованное описание исключения.
5. Метод
String getMessage()
возвращает описание исключения.
6. Метод
StackTraceElement[] getStackTrace()
возвращает массив, содержащий поэлементную трассировку стека в виде объектов класса StackTraceElement.
7. Метод
final Throwable[] getSuppressed()
получает подавленные исключения, связанные с вызывающим исключением, и возвращает массив, который содержит результат. Подавленные исключения генерируются в операторе try с ресурсами.
8. Метод
Throwable initCause(Throwable причина_исключения)
связывает входной параметр причина_исключения с вызывающим исключением, указывая его как причину этого вызывающего исключения. Возвращает ссылку на исключение. Метод используется при создании цепочек исключений.
9. Метод
printStackTrace();
выводит трассировку стека.
10. Метод printStackTrace() имеет еще две перегруженных реализации
void printStackTrace(PrintStream поток_вывода) void printStackTrace(PrintWriter поток_вывода)
Метод направляет трассировку стека в заданный поток_вывода.
11. Метод
void setStackTrace(StackTraceElement элементы[])
устанавливает трассировку стека для заданных элементов.
12. Метод
String toString()
возвращает объект типа String содержащий описание исключения. Этот метод можно вызвать из метода println() при выводе объекта типа Throwable.
⇑
6. Пример использования некоторых методов класса Throwable. Разработка собственного класса исключения
В примере демонстрируется использование некоторых методов класса Throwable:
- getLocalizedMessage();
- getMessage();
- toString();
- getStackTrace();
- fillInStackTrace().
Объявляется класс MyException, унаследованный от класса Exception. В иерархии классов исключений Java класс Exception унаследован от класса Throwable. Поэтому, класс MyException может использовать и переопределять методы класса Throwable.
Текст программы следующий:
import java.util.Scanner; // собственный класс исключения, унаследован от Exception class MyException extends Exception { // переопределенная функция getLocalizedMessage() public String getLocalizedMessage() { return "MyException.getLocalizedMessage()"; } } // класс, содержащий функцию main() public class Train04 { // функция main() тестирует работу класса MyException public static void main(String[] args) { // Ввести число x. Если число за пределами [0..100], // то сгенерировать исключение MyException int x; Scanner sc = new Scanner(System.in); System.out.print("x = "); x = sc.nextInt(); // ввести x try { // сгенерировать исключение (создать объект типа MyException), // если x за пределами [0..100] if ((x<0)||(x>100)) throw new MyException(); System.out.println("OK!"); } catch(MyException e) { // обработка исключения типа MyException, // демонстрация некоторых методов класса Throwable System.out.println("Return from getLocalizedMessage(): " + e.getLocalizedMessage()); System.out.println("Return from getMessage(): " + e.getMessage()); System.out.println("Method printStackTrace(): "); e.printStackTrace(); System.out.println("Method toString(): " + e.toString()); System.out.println("------------------------"); System.out.println("Method getStackTrace(). Stack trace: "); StackTraceElement[] stE; stE = e.getStackTrace(); // метод getStackTrace() for (int i=0;i<stE.length;i++) System.out.println(stE[i].toString()); System.out.println("-------------------------"); System.out.println("Method fillStackTrace(). Stack trace: "); Throwable tA = e.fillInStackTrace(); StackTraceElement[] stE2 = tA.getStackTrace(); for (int i=0; i<stE2.length; i++) System.out.println(stE[i].toString()); System.out.println("-------------------------"); } } }
Объясним некоторые фрагменты кода.
С целью демонстрации в классе MyException переопределяется метод getLocalizedMessage(). При вызове этого метода выводится сообщение из этого переопределенного метода. По данному примеру можно переопределять другие методы класса Throwable.
В функции main() продемонстрировано использование методов класса Throwable. Вводится переменная x, которая проверяется на допустимые значения в пределах то 0 до 100. Если значение x меньше 0 или больше 100, то генерируется исключение типа MyException.
Результат работы программы
x = 200 Return from getLocalizedMessage(): MyException.getLocalizedMessage() Return from getMessage(): null Method printStackTrace(): Method toString(): MyException: MyException.getLocalizedMessage() ------------------------ Method getStackTrace(). Stack trace: Train04.main(Train04.java:36) ------------------------- Method fillStackTrace(). Stack trace: Train04.main(Train04.java:36) ------------------------- MyException: MyException.getLocalizedMessage()
⇑
Связанные темы
- Исключения. Исключительная ситуация. Ключевые слова try, catch, finally. Примеры
- Операторы throw, throws. Примеры
- Класс Exception. Создание собственных классов исключений. Примеры
⇑
Эта статья посвящается очень важному вопросу программирования — исключительным ситуациям и ошибкам (exceptions and errors).
В языке Java исключения (Exceptions) и ошибки (Errors) являются объектами. Когда метод вызывает, еще говорят «бросает» от слова «throws», исключительную ситуацию, он на самом деле работает с объектом. Но такое происходит не с любыми объектами, а только с теми, которые наследуются от Throwable.
Упрощенную диаграмму классов ошибок и исключительний вы можете увидеть на следующем рисунке:
RuntimeException, Error и их наследников еще называют unchecked exception, а всех остальных наследников класса Exception — checked exception.
Checked Exception обязывает пользователя обработать ее (использую конструкцию try-catch) или же отдать на откуп обрамляющим методам, в таком случае к декларации метода, который бросает проверяемое (checked) исключение, дописывают конструкцию throws, например:
public Date parse(String source) throws ParseException { ... }
К unchecked исключениям относятся, например, NullPointerException, ArrayIndexOutOfBoundsException, ClassCastExcpetion и так далее. Это те ошибки, которые могут возникнут практически в любом методе. Несомненно, описывать каждый метод как тот, который бросает все эти исключения, было бы глупо.
1. Так когда же нужно бросать ошибки?. На этот вопрос можно ответить просто: если в методе возможна ситуация, которую метод не в состоянии обработать самостоятельно, он должен «бросать» ошибку. Но ни в коем случае нельзя использовать исключительные ситуации для управления ходом выполнения программы.
Чаще всего Exceptions бросаются при нарушении контракта метода. Контракт (contract) — это негласное соглашение между создателем метода (метод сделает и/или вернет именно то, что надо) и пользователем метода (на вход метода будут передаваться значения из множества допустимых).
Нарушение контракта со стороны создателя метода — это, например, что-нибудь на подобии MethodNotImplementedYetException :).
Пользователь метода может нарушить контракт, например, таким способом: на вход Integer.parseInt(String) подать строку с буквами и по заслугам получить NumberFormatException.
Часто при реализации веб-сервисов первыми строками методов я пишу конструкции вида:
public Contract getContractById(String id) {
if (id == null) throw new NullPointerException("id is null");
...
}
Это помогает на вызывающей стороне понять, что они нарушают контракт метода, причиной чего часто может быть ошибка в логике их же приложения.
2. А что собственно бросать?. Выбор не то чтобы сильно велик, но и не однозначен: checked, unchecked (runtime), unchecked (error).
Сразу скажу, в подавляющем большинстве случаев Error вам не понадобится. Это в основном критические ошибки (например, StackOverflowError), с которыми пусть работает JVM.
Checked Exceptions, как было написано выше, заставляет программиста-пользователя написать код для ее обработки или же описать метод как «вызывающий исключительную ситуацию».
С unchecked exception можно поступить по-разному. В случае с такими ошибками, пользователь сам решает, будет он обрабатывать эту ошибку, или же нет (компилятор не заставляет это делать).
Можно написать следующее простое правило: если некоторый набор входящих в метод данных может привести к нарушению контракта, и вы считаете, что программисту-пользователю важно разобраться с этим (и что он сможет это сделать), описывайте метод с конструкцией throws, иначе бросайте unchecked exception.
3. Ну и как это обрабатывать? Обрабатывать ошибку лучше там, где она возникла. Если в данном фрагменте кода нет возможности принять решение, что делать с исключением, его нужно бросать дальше, пока не найдется нужный обработчик, либо поток выполнения программы не вылетит совсем.
Вы наверняка знаете, что обработка исключений происходит с помощью блока try-catch-finally. Сразу скажу вам такую вещь: никогда не используйте пустой catch блок!. Выглядит этот ужас так:
try { ... }
catch(Exception e) { }
Если Вы уверены, что исключения в блоке try не возникнет никогда, напишите комментарий, как например в этом фрагменте кода:
StringReader reader = new StringReader("qwerty");
try { reader.read(); }
catch (IOException e) { /* cannot happen */ }
Если же исключение в принципе может возникнуть, но только действительно в «исключительной ситуации» когда с ним ничего уже сделать будет нельзя, лучше оберните его в RuntimeException и пробросьте наверх, например:
String siteUrl = ...;
...
URL url;
try { url = new URL(siteUrl); }
catch (MalformedURLException e) {
throw new RuntimeException(e);
}
Скорее всего ошибка здесь может возникнуть только при неправильной конфигурации приложения, например, siteUrl читается из конфигурационного файла и кто-то допустил опечатку при указании адреса сайта. Без исправления конфига и перезапуска приложения тут ничего поделать нельзя, так что RuntimeException вполне оправдан.
4. Зачем нужно все это делать? А почему бы и нет :). Если серьезно — правильное использование Exceptions и корректная их обработка сделают код более понятным, гибким, структурированным и возможным для повторного использования.
Updated 28.08.2009: Хочу показать вам несколько интересных моментов, которые касаются исключений и блоков try-catch-finally.
Можно ли сделать так, чтобы блок finally не выполнился? Можно:
public class Test1 {
public static void main(String[] args) {
try {
throw new RuntimeException();
} catch (Exception e) {
System.exit(0);
} finally {
System.out.println("Please, let me print this.");
}
}
}
Ну и еще одна интересная вещь. Какое исключение будет выброшено из метода:
public class Test {
public static void main(String[] args) {
try {
throw new NullPointerException();
} catch (NullPointerException e) {
throw e;
} finally {
throw new IllegalStateException();
}
}
}
Правильный ответ — IllegalStateException. Не смотря на то, что в блоке catch происходит повторный «выброс» NPE, после него выполняется блок finally, который перехватывает ход выполнения программы и бросает исключение IllegalStateException.
Жду ваших вопросов и комментариев.
Определение
понятия ошибки и исключения.
Классификация
ошибок.
Общий способ обработки
ошибок.
Обработка ошибок в языке Java.
— исключение в Java.
— причины возникновения исключений
в Java
— конструкция обработки исключения
— асинхронные исключения
—
иерархия исключений
—
классы Exception и RuntimeException
— класс Error
Приложения.
Определение понятия ошибки и исключения.
В
качестве введения рассмотрим определения
понятия «ошибка». Начнем с наиболее
общего трактования этого:
В самом
общем случае под ошибкой понимается
какой-то сбой в программе на этапе ее
выполнения.
По определению стандарта
ISO
9241-13 ошибка это – несоответствие между
целями пользователя и ответом системы.
Ошибкой также можно назвать
недокументированные или нежелательные,
«побочные» реакции программы на
те или иные действия пользователя равно
как и при использовании ее одновременно
с другим программами или на другой
аппаратной платформе.
В книге «К.
Браун, Р. Калбертсон, Г. Кобб. Быстрое
тестирование» приводится такое
определение программных ошибок: «Говоря
простыми словами, программная ошибка
— не что иное, как изъян в разработке
программного продукта, который вызывает
несоответствие ожидаемых результатов
выполнения программного продукта и
фактически полученных результатов.
Дефект может возникнуть на стадии
кодирования, на стадии формулирования
требований или на стадии проектирования,
либо же его причина может крыться в
некорректной конфигурации или данных.
Дефектом может быть также что-то другое,
что не соответствует ожиданиям заказчика
и что может быть, а может и не быть
определено в спецификации программного
продукта».
Для исключения Г.
Шилдт дает такое определение: исключение
– это нештатная ситуация , возникающая
во время выполнения последовательности
кода.
Как можно заметить, под понятием
ошибки и исключительной ситуацией можно
подразумевать одно и то же.
Исключение
— это некое специальное событие, которое
сигнализирует об ошибке в программе.
Другими
словами, исключение – это ошибка времени
выполнения.
Классификация
ошибок.
Ошибки
при написании, отладке и работе программ
можно разделить на этапы их времени
возникновения, такие как: ошибки
компиляции, выполнения, компоновки и
логические ошибки.
Ошибки компиляции
обнаруживаются при непосредственной
трансляции исходного кода в объектный
модуль или в машинный код. Невозможно
перейти к стадии времени выполнения
программы, пока не будут ликвидированны
все ошибки стадии компиляции.
Ошибки
выполнения относятся
к самой непредсказуемой группе . Прежде
всего они могут иметь разную природу,
и соответственно по-разному проявляться.
Часть ошибок обнаруживается и
обрабатываются операционной системой.
Ошибки компоновки, как следует из
названия, связаны с проблемами,
обнаруженными при разрешении внешних
ссылок. В разных языках может осуществляться
на различных этапах.
Логические
ошибки имеют разную природу. Так они
могут следовать из ошибок, допущенных
при проектировании, например, при выборе
методов, разработке алгоритмов или
определении структуры классов, а могут
быть непосредственно внесены при
кодировании модуля.
Ошибки
компиляции:
1. Синтаксические
ошибки.
2. Семантические ошибки.
1. Описания идентификаторов.
1. Неинициализированный
указатель.
2.
Неинициализированная переменная.
3. Ошибочная инициализация.
2. Статический контроль
типов.
1. Не корректное
присваивание.
2. Не
корректная операция.
3. Не корректная передача параметров.
Ошибки
выполнения:
1. Синхронные ошибки.
1. Ошибки определения данных.
1. Ошибки передачи.
2.
Ошибки преобразования.
3.
Ошибки перезаписи.
4. Ошибочные
данные.
5. Динамический
контроль типов.
6. Ошибки
индексации.
2. Ошибки накопления
погрешностей.
1. Игнорирование
способов уменьшения погрешностей.
2. Переполнение разрядной
сетки.
3. Арифметические ошибки.
4. Ссылочные ошибки.
5. Ошибки
сети.
6. Ошибки ввода/вывода.
2.
Асинхронные ошибки.
1. Ошибки
виртуальной машины.
2. Ошибки системы.
Ошибки
компоновки
1. Ошибки получения
данных по внешним ссылкам.
2.
Объединение модулей
1. Ошибки
обнаружения модулей.
2.
Ошибка состыковки списков параметров
модулей.
Логические
ошибки
1. Ошибки проектирования
1. Неприменимый метод.
2. Неверный алгоритм.
3. Неверная структура данных.
2.
Ошибки кодирования
1.
Некорректное вычисление.
2. Ошибки реализации алгоритмов.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #




