finally. Встроенные исключения Java. Создание собственных подклассов исключений. Сцепленные исключения
finally Когда исключение возбуждено, выполнение метода направляется по нелинейному пути, изменяющему нормальный поток управления внутри метода. В зависимости от того, как закодирован метод, существует даже возможность преждевременного возврата управления. В некоторых методах это может служить причиной серьезных проблем. Например, если метод при входе открывает файл и закрывает его при выходе, вероятно, вы не захотите, чтобы выполнение кода, закрывающего файл, было пропущено из-за применения механизма обработки исключений. Ключевое слово finally предназначено для того, чтобы справиться с такой ситуацией. finally создает блок кода, который будет выполнен после завершения блока try/catch, но перед кодом, следующим за try/catch. Блок finally выполняется независимо от того, возбуждено исключение или нет. Если исключение возбуждено, блок finally выполняется, даже если ни один оператор catch этому исключению не соответствует. В любой момент, когда метод собирается возвратить управление вызывающему коду изнутри блока try/catch – из-за необработанного исключения, или явным применением оператора return – блок finally будет выполнен перед возвратом управления из метода. Это может быть удобно для закрытия файловых дескрипторов либо освобождения других ресурсов, которые были получены в начале метода и должны быть освобождены перед возвратом. Оператор finally необязателен. Однако каждый оператор try требует наличия, по крайней мере, одного оператора catch или finally. Ниже приведен пример программы, которая показывает три метода, возвращающих управление разными способами, но ни один из них не пропускает выполнения блока finally. class FinallyDemo { // Возбуждает исключение из метода.
static void procA() { try { System. out. println(" внутри procA" ); throw new RuntimeException(" демо" ); } finally { System. out. println(" блок finally procA" ); } } // Возврат управления в блоке try. static void procB() { try { System. out. println(" внутри procB" ); return; } finally { System. out. println(" блок finally procB" ); } } // Нормальное выполнение блока try. static void procC() { try { System. out. println(" внутри procC" ); } finally { System. out. println(" блок finally procC" ); } } public static void main(String args[]) { try { procA(); } catch (Exception e) { System. out. println(" Исключение перехвачено" ); } procB(); procC(); }} В этом примере procA() преждевременно прерывает выполнение в блоке try, возбуждая исключение. Блок finally все равно выполняется. В procB() возврат управления осуществляется в блоке try оператором return. Блок finally выполняется перед возвратом из procB(). В procC() блок try выполняется нормально, без ошибок. Однако блок finally выполняется все равно. Встроенные исключения Java Внутри стандартного пакета java. lang определено несколько классов исключений. Некоторые из них использовались в предшествующих примерах. Наиболее общие из этих исключений являются подклассами стандартного типа RuntimeException. Как уже объяснялось ранее, эти исключения не нужно включать в список throws метода – они называются непроверяемыми исключениями, поскольку компилятор не проверяет факт обработки или возбуждения методом таких исключений. Создание собственных подклассов исключений Хотя встроенные исключения Java обрабатывают большинство частых ошибок, вероятно, вам потребуется создать ваши собственные типы исключений для обработки ситуаций, специфичных для ваших приложений. Это достаточно просто сделать: просто определите подкласс Exception (который, разумеется, является подклассом Throwable). Ваши подклассы не обязаны реализовывать что-либо – важно само их присутствие в системе типов, которое позволит использовать их как исключения. Класс Exception не определяет никаких собственных методов. Естественно, он наследует методы, представленные в Throwable. Таким образом, всем исключениям, включая те, что вы создадите сами, доступны методы, определенные в Throwable.
Exception определяет четыре конструктора. Два были добавлены в JDK 1. 4 для поддержки цепочек исключений. Сцепленные исключения Начиная с J2SE 1. 4, в подсистему исключений было добавлено новое средство: сцепленные исключения (chained exceptions). Это средство позволяет ассоциировать с одним исключением другое исключение. Второе исключение описывает причину появления первого. Например, представьте ситуацию, когда метод возбуждает исключение ArithmeticException, поскольку была предпринята попытка деления на ноль. Однако реальная причина проблемы заключается в ошибке ввода-вывода, что приводит к неправильному делению. И хотя метод должен возбуждать ArithmeticException, так как произошла именно эта ошибка, вы можете также позволить вызывающему коду узнать о том, что в основе лежит ошибка ввода-вывода. Сцепленные исключения позволяют справиться с этой, а также с любой другой ситуацией, в которой присутствуют уровни исключений. Чтобы разрешить сцепленные исключения, были добавлены два конструктора и два метода к Throwable. // Демонстрация сцепленных исключений. class ChainExcDemo { static void demoproc() { // создать исключение NullPointerException e = new NullPointerException(" верхний уровень" ); // добавить причину e. initCause(new ArithmeticException(" причина" )); throw e; } public static void main(String args[]) { try { demoproc(); } catch(NullPointerException e) { BookNew_JAVA-7. indb 250 02. 06. 2007 1: 07: 00 Глава 10. Обработка исключений 251 // отобразить исключение верхнего уровня System. out. println(" Перехвачено: " + e); // отобразить исключение-причину System. out. println(" Исходная причина: " + e. getCause()); } }} Эта программа создает следующий вывод: Перехвачено: java. lang. NullPointerException: верхний уровень Исходная причина: java. lang. ArithmeticException: причина В этом примере исключением верхнего уровня является NullPointerException. К нему добавлено исключение-причина – ArithmeticException. Когда исключение возбуждается из demoproc(), оно перехватывается в main(). Затем исключение верхнего уровня отображается, а за ним следует исключение, лежащее в основе, которое извлекается методом getCause(). Сцепленные исключения могут вкладываться на любую глубину. То есть исключениепричина может иметь собственную причину. Но имейте в виду, что слишком длинные цепочки сцепленных исключений, скорее всего, свидетельствуют о плохом дизайне.
Сцепленные исключения не являются вещью, совершенно необходимой в каждой программе. Однако в случаях, когда информация об исключении-причине таки нужна, они представляют собой элегантное решение.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|