Вводный курс. Язык программирования Java
- Вводный курс. Язык программирования Java
- Просмотров: 5922
34. Исключения
Исключение (exception) — это ошибка, возникающая во время выполнения (runtime) программы. Исключения могут возникать во многих случаях, например: деление на нуль, нулевая ссылка, выход за границы массива, попытка открыть несуществующий файл и другие. Но это не обязательно ошибки программиста. Существуют ситуации, предусмотреть которые невозможно, например, сбой оборудования.
Если возникает ошибка, обработка которой в программе не предусмотрена, выполнение программы будет прервано в строке кода, содержащей ошибку. Такое аварийное завершение работы программы не очень хорошее решение. Рассмотрим, какие решения предлагает Java.
Обработка исключений
Как и всё в Java, исключения тоже представлены в виде классов. Исключение в Java - это объект класса Exception, который содержит информацию об ошибке, включая тип ошибки и состояние программы, в котором произошла ошибка. Создание объекта-исключения и передача его на выполнение называется броском исключения (throw). Говорят, что исключение выбрасывается в метод. По получении объекта исключения метод может обработать его или передать для обработки дальше
Для обработки исключений используется конструкция try-catch-finally. В блок try помещается программный код, который потенциально может привести к ошибке. Если исключительная ситуация возникает, то управление передается в блок catch, в который помещается программный код обработки исключения. Если в блоке try исключительной ситуации не возникает, блок catch пропускается. Программный код в блоке finally выполняется всегда.
try {
//здесь код, который может привести к ошибке
} catch(Имя класса исключения ex ){ //указывается класс исключения
//здесь код обработки исключения
}
finally{ // блок finally не обязателен
// выполняется в любом случае
}
В заголовке блока catch, указывается имя класса исключения, для которого предназначен этот блок. Блок будет срабатывать только при возникновении данного исключения или исключения класса – наследника.
Имя ex в заголовке catch-блока — это произвольное имя. Оно служит для именования объекта-исключения и с его помощью можно извлечь информацию о возникшем исключении.
В Java используются следующие ключевые слова для работы с исключениями:
- try — начало блока кода, который может привести к ошибке
- catch — начало блока кода обработки исключений
- finally — начало блока кода, которой выполняется в любом случае
- throw — служит для генерации исключений
- throws — обозначает, что метод может выбросить исключение
Пример программы, в которой не обрабатывается исключительная ситуация, заключающейся в делении на ноль.
public class MyException {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
System.out.println("Результат 1/n= " + 1/n);
System.out.println("Программа завершена");
}
}
После запуска программы при вводе числа 0 на консоль будет выведено следующее сообщение:
0
Exception in thread "main" java.lang.ArithmeticException: / by zero
at myexception.MyException.main(MyException.java:13)
в подпроцессе "main" произошло исключение класса ArithmeticException деления на нуль: "/ by zero". Исключение возникло при выполнении метода main класса MyException.
Выполнение программы прервано на операторе System.out.println("Результат 1/n= " + 1/n); Последующая строка кода System.out.println("Программа завершена"); не выполняется и сообщение «Программа завершена» не выводится.
Выполним обработку исключительной ситуации – деление на нуль. Для отслеживания ошибки код, который ее вызывает, заключаем в блок try, а для обработки ошибки используем блок catch. Обработка ошибки – это просто вывод типа исключения.
public class MyException {
public static void main(String[] args) {
try{
Scanner in = new Scanner(System.in);
int n = in.nextInt();
System.out.println("Результат 1/n= " + 1/n);
} catch(Exception e) {
System.out.println("Исключение:" +e);
}finally{
System.out.println("Программа завершена");
}
}
}
После запуска программы при вводе числа 0 на консоль будет выведено следующее сообщение:
0
Исключение:java.lang.ArithmeticException: / by zero
Программа завершена
При делении на ноль выводится сообщение: «Исключение:java.lang.ArithmeticException: / by zero». Здесь важно то, что после попытки деления на ноль программа продолжает работу и выполняется блок finally.
Для блока try-catch может быть несколько блоков catch — каждый для своего исключения.
Пример.
Scanner in = new Scanner(System.in);
int n = in.nextInt();
try {
inputFile("data.txt");
System.out.println("Результат 1/n= " + 1/n);
} catch ( FileNotFoundException fe ) {
System.out.println("Файл data.txt не найден");
} catch ( ArithmeticException e ) {
System.out.println("Деление на ноль");
}
Если в блоке try возникнет одна из двух исключительных ситуаций — FileNotFoundException или ArithmeticException, то она будут перехвачена и сработает соответствующий блок catch. Если возникнет какое-то другое исключение, то оно не будет перехвачено и работа программы будет аварийно завершена.
Классы исключительных ситуаций
Теперь мы знаем, как обрабатывать исключения, но возникает вопрос, какие исключения обрабатывать? Для ответа на него рассмотрим основные классы исключений
Throwable
|
+------- Error
|
+------- Exceptoin
|
+------- RunTimeExceptoin
|
Throwable — базовый класс для всех исключительных ситуаций.
Error — базовый класс для исключительных ситуаций, вызванных серьёзными сбоями в работе виртуальной машины Java, поэтому не следует пытаться обрабатывать такие исключительные ситуации в собственной программе, поскольку на уровне программы их обработать невозможно. Например, устранить нехватку памяти или переполнение стека.
Exception — это базовый класс для всех тех исключений, которые являются результатом проблем в программе, которые могут быть обработаны и предсказуемы.
RuntimeException - это подкласс класса Exception. Он занимает особое место. К этому классу относятся ошибки времени выполнения программы – это ошибки программиста. Например, произошло деление на ноль, выход за границы массива, попытка открыть несуществующий файл. Эти ошибки необходимо предусмотреть и устранить без привлечения исключений. Использовать исключения следует только в крайних ситуациях. Следует помнить, что перехват и обработка исключений требует больших затрат и снижает быстродействие программы, поэтому злоупотреблять ими не следует.
Транслятор автоматически обрабатывает ошибки класса RuntimeException, поэтому в программе обрабатывать эти ошибки не нужно.
Классы Error и RuntimeException образуют группу непроверяемых исключительных ситуаций – программисту их проверять не нужно.
Вот перечень основных непроверяемых исключений класса RuntimeException
Класс исключения |
Описание |
ArithmeticException |
Арифметическая ошибка (например, деление на ноль) |
ArrayIndexOutOfBoundsException |
Индекс массива за пределами допустимых границ |
ArrayStoreException |
Присваивание элементу массива недопустимого значения |
ClassCastException |
Недопустимое приведение типов |
IllegalArgumentException |
Методу передан недопустимый аргумент |
IndexOutOfBoundsException |
Некоторый индекс находится за пределами допустимых для него границ |
NegativeArraySizeException |
Создание массива отрицательного размера |
NullPointerException |
Недопустимое использование нулевого указателя |
NumberFormatException |
Недопустимое преобразование текстовой строки в числовой формат |
StringIndexOutOfBoundsException |
Попытка индексирования вне пределов строки |
UnsupportedOperationException |
Недопустимая операция |
Все остальные классы, образованные от класса Exception, называются проверяемыми исключениями – их необходимо проверять в коде программы.
Перечень основыных проверяемых исключений:
· CloneNotSupportedException: класс, для объекта которого вызывается клонирование, не реализует интерфейс Clonable
· InterruptedException: поток прерван другим потоком
ClassNotFoundException: невозможно найти класс
Поскольку все классы исключений наследуются от класса Exception, то все они наследуют ряд его методов, которые позволяют получить информацию о характере исключения. Среди этих методов отметим наиболее важные:
Метод |
Описание |
fillInStackTrace() |
возвращает объект Throwable, который содержит полную трассировку стека |
getLocalizesMessage() |
возвращает строку с локализованным описанием исключения |
getMessage() |
возвращает строку с описанием исключения |
printStackTrace() |
возвращает массив, содержащий трассировку стека исключения |
toString() |
возвращает объект класса String, содержащий описание исключения |
Оператор throw
Оператор throw предназначен для явного вызова исключения в требуемом месте программы. После выполнения оператора throw последующие операторы не выполняются, и ищется ближайший блок try ... catch, соответствующего типу исключения, для обработки исключения. Если подходящий блок не будет найден, то обработчик исключений остановит программу и выдаст состояние стека вызовов.
Пример.
С помощью оператора throw создаем (бросаем) исключение и затем перехватываем в блоке catch. В программе происходит ввод числа, и если число равно 0, то возникает исключение:
public static void main(String[] args) {
try{
Scanner in = new Scanner(System.in);
int n = in.nextInt();
if(n == 0){
throw new Exception("Число n равно нулю");
}
}
catch(Exception ex){
System.out.println(ex.getMessage());
} finally{
System.out.println("Программа завершена");
}
}
Будет выведено
0
Число n равно нулю
Программа завершена
Оператор throws
Если метод выбрасывает или может выбросить исключение, которое в методе не обрабатывается, то при описании метода используется оператор throws, который надо обработать при вызове этого метода. В сигнатуре метода после ключевого слова throws перечисляются классы исключений, которые может выбрасывать метод.
Пример.
// Описание метода:
static void method(int n) throws Exception{
// Выбрасывание исключения:
if(n == 0){
throw new Exception("Ошибка в методе method. Число n равно нулю");
}
System.out.println("Работает method!");
}
public static void main(String[] args) {
try{
method(0);
// Метод выбрасывает исключение
}catch(Exception e){
// Обработка исключения
System.out.println("Обработка исключения: "+e);
}
Будет выведено:
Обработка исключения: java.lang.Exception: Ошибка в методе method. Число n равно нулю