Выбрать главу

В предыдущих примерах программ обрабатывались исключения, автоматически генерируемые виртуальной машиной Java. Но генерировать исключения можно и вручную, используя для этого оператор throw. Ниже приведена общая форма этого оператора. throw объект_исключения;

где объект_исключения должен быть объектом класса, производного от класса Throwable.

Ниже приведен пример программы, демонстрирующий применение оператора throw. В этой программе исключение ArithmeticException генерируется вручную. // Генерирование исключения вручную, class ThrowDemo { public static void main(String args[]) { try { System.out.println("Before throw."); // Генерирование исключения. throw new ArithmeticException() ; } catch (ArithmeticException exc) { // перехватить исключение System.out.println("Exception caught."); } System.out.println("After try/catch block."); } }

Выполнение этой программы дает следующий результат: Before throw. Exception caught. After try/catch block. `

Обратите внимание на то, что исключение ArithmeticException генерируется с помощью ключевого слова new в операторе throw. Дело в том, что оператор throw генерирует исключение в виде объекта. Поэтому после ключевого слова throw недостаточно указать только тип исключения, нужно еще создать объект для этой цели. Повторное генерирование исключений

Исключение, перехваченное блоком catch, может быть повторно сгенерировано для обработки другим аналогичным блоком. Чаще всего повторное генерирование исключений применяется с целью предоставить разным обработчикам доступ к исключению. Так, например, повторное генерирование имеет смысл в том случае, если один обработчик оперирует одним свойством исключения, а другой обработчик ориентирован на другое его свойство. Повторно сгенерированное исключение не может быть перехвачено тем же самым блоком catch. Оно распространяется в другие блоки catch.

Ниже приведен пример программы, демонстрирующий повторное генерирование исключений. //•Повторное генерирование исключений, class Rethrow { public static void genException() { // Массив numer длиннее маесивв denom. int numer[] = { 4, 8, 16, 32, 64, 128, 256, 512 }; int denom[] = { 2, 0, 4, 4, 0, 8 }; for(int i=0; i<numer.length; i++) { try { System.out.println(numer[i] + " / " + denom[i] + " is " + numer[i]/denom[i]); } catch (ArithmeticException exc) { // перехватить исключение System.out.println("Can11 divide by Zero!"); } catch (ArraylndexOutOfBoundsException exc) { // перехватить исключение System.out.println("No matching element found."); throw exc; // Повторное генерирование исключения. } } } } class RethrowDemo { public static void main(String args[]) { try { Rethrow.genException(); } catch(ArraylndexOutOfBoundsException exc) { // Перехват повторно сгенерированного включения. System.out.println("Fatal error - " + "program terminated."); } } }

В данной программе ошибка деления на нуль обрабатывается локально в методе genException (), а при попытке обращения за границы массива исключение генерируется повторно. На этот раз оно перехватывается в методе main (). Подробнее о классе Throwable

В приведенных до сих примерах программ только перехватывались исключения, но не выполнялось никаких действий над представляющими их объектами. В выражении оператора catch указываются тип исключения и параметр, принимающий объект исключения. А поскольку все исключения представлены подклассами, производными от класса Throwable, то они поддерживают методы, определенные в этом классе. Некоторые наиболее употребительные методы из класса Throwable приведены в табл. 9.1.

Таблица 9.1. Наиболее употребительные методы из класса Throwable Метод Описание Throwable filllnStackTrace() Возвращает объект типа Throwable, содержащий полную трассировку стека исключений. Этот объект пригоден для повторного генерирования исключений String getLocalizedMessage() Возвращает описание исключения, локализованное по региональным стандартам String getMessage() Возвращает описание исключения void printStackTrace() Выводит трассировку стека исключений void printStackTrace(PrintStream stream) Выводит трассировку стека исключений в указанный поток void printStackTrace(PrintWriter stream) Направляет трассировку стека исключений в указанный поток String toString() Возвращает объект типа String, содержащий полное описание исключения. Этот метод вызывается из метода println() при выводе объекта типа Throwable

Среди методов, определенных в классе Throwable, наибольший интерес представляют методы pr intStackTrace () и toString(). С помощью метода printStackTrace () можно вывести стандартное сообщение об ошибке и запись последовательности вызовов методов, которые привели к возникновению исключения, А метод toString () позволяет получить стандартное сообщение об ошибке. Этот метод также вызывается в том случае, когда объект исключения передается в качестве параметра методу println (). Применение этих методов демонстрируется в следующем примере программы: // Применение методов из класса Throwable. class ExcTest { static void genException() { int nums[] = new int[4]; System.out.println("Before exception is generated."); // сгенерировать исключение в связи с попыткой // обращения за границы массива nums[7] = 10; System.out.println("this won't be displayed"); } } class UseThrowableMethods { public static void main(String args[]) { try { ExcTest.genException() ; } catch (ArraylndexOutOfBoundsException exc) { // перехватить исключение System.out.println("Standard message is: "); System.out.println(exc) ; System.out.println("\nStack trace: "); exc.printStackTrace(); } System.out.println("After catch statement."); } }

Результат выполнения данной программы выглядит следующим образом: Before exception is generated. Standard message is: java.lang.ArraylndexOutOfBoundsException: 7 Stack trace: java.lang.ArraylndexOutOfBoundsException: 7 at ExcTest.genException(UseThrowableMethods.java:10) at UseThrowableMethods.main(UseThrowableMethods.java:19) After catch statement. Использование ключевого слова finally

Иногда требуется определить кодовый блок, который должен выполняться по завершении блока try/catch. Допустим, в процессе работы программы возникло исключение, требующее ее преждевременного завершения. Но в программе открыт файл или установлено сетевое соединение, а следовательно, файл нужно закрыть, а соединение разорвать. Для выполнения подобных операций нормального завершения программы удобно воспользоваться ключевым словом finally.

Для того чтобы определить код, который должен выполняться по завершении блока try/catch, нужно указать блок finally в конце последовательности операторов try/catch. Ниже приведена общая форма записи блока try/catch вместе с блоком finally. try { // Блок кода, в котором отслеживаются ошибки. } catch (тип_исключения_1 объект_исключения) { // Обработчик исключения тип_исключения_1 ) catch (тип_исключения_2 объект_исключения) { // Обработчик исключения тип_исключения_2 } //. . . finally { // Код блока finally }

Блок finally выполняется всегда по завершении блока try/catch независимо от того, какое именно условие к этому привело. Следовательно, блок finally получит управление как при нормальной работе программы, так и при возникновении ошибки. Более того, он будет вызван даже в том случае, если в блоке try или в одном из блоков catch будет присутствовать оператор return для немедленного возврата из метода.

Ниже приведен краткий пример программы, демонстрирующий применение блока finally. // Применение блока finally, class UseFinally { public static void genException(int what) { int t; int nums[] = new int[2]; System.out.println("Receiving " + what); try { switch(what) { case 0: t = 10 / what; // сгенерировать ошибку деления на нуль break; case 1: nums[4] = 4; // сгенерировать ошибку обращения к массиву break; case 2: return; // возвратиться из блока try } } catch (ArithmeticException exc) { // перехватить исключение System.out.println("Can1t divide by Zero!"); return; // возвратиться из блока catch } catch (ArraylndexOutOfBoundsException exc) { // перехватить исключение System.out.println("No matching element found."); } // Этот блок выполняется независимо от того, каким // образом завершается блок try/catch. finally { System.out.println("Leaving try."); } } } class FinallyDemo { public static void main(String args[]) { for(int i=0; i < 3; i++) { UseFinally.genException(i); System.out.println() ; } } }