Чтение онлайн

ЖАНРЫ

Java: руководство для начинающих
Шрифт:

Ниже приведен краткий пример программы, демонстрирующий применение многократного перехвата исключений. // Применение средства многократного перехвата исключений. // Примечание: для компиляции этого кода требуется JDK 7 // или более поздняя версия данного комплекта, class MultiCatch { public static void main(String args[]) { int a=88, b=0; int result; char chrs[] = { 'А', 'В', 'C' }; for(int i=0; i < 2; i++) { try { if (i == 0) // сгенерировать исключение ArithmeticException result = а / b; else // сгенерировать исключение ArraylndexOutOfBoundsException chrs[5] = 'X'; } // В этом операторе catch организуется перехват обоих исключений, catch(ArithmeticException | ArraylndexOutOfBoundsException е) { System.out.println("Exception caught: " + e); } } System.out.println("After multi-catch."); } }

В данном примере программы исключение ArithmeticException генерируется при попытке деления на нуль, а исключение ArraylndexOutOfBoundsException —

при попытке обращения за границы массива chrs. Оба исключения перехватываются одним оператором catch.

Средство более точного повторного генерирования исключений ограничивает этот процесс лишь теми проверяемыми типами исключений, которые генерируются в соответствующем блоке try и не обрабатываются в предыдущем блоке оператора catch, а также относятся к подтипу или супертипу указываемого параметра. И хотя такая возможность требуется нечасто, ничто не мешает теперь воспользоваться ею в полной мере. А для организации окончательного повторного генерирования исключений параметр оператора catch должен быть, по существу, указан как final. Это означает, что ему нельзя присвоить новое значение в блоке catch. Он может быть указан как final явным образом, хотя это и не обязательно. Встроенные в Java исключения

В стандартном пакете java. lang определены некоторые классы, представляющие стандартные исключения Java. Часть из них использовалась в предыдущих примерах программ. Наиболее часто встречаются исключения из подклассов стандартного класса RuntimeException. А поскольку пакет java. lang импортируется по умолчанию во все программы на Java, то исключения, производные от класса RuntimeException, становятся доступными автоматически. Их даже обязательно включать в список оператора throws. В терминологии языка Java такие исключения называют непроверяемыми, поскольку компилятор не проверяет, обрабатываются или генерируются подобные исключения в методе. Непроверяемые исключения, определенные в пакете java.lang, приведены в табл. 9.2, тогда как в табл. 9.3 — те исключения из пакета j ava. lang, которые следует непременно включать в список оператора throws при объявлении метода, если, конечно, в методе содержатся операторы, способные генерировать эти исключения, а их обработка не предусмотрена в теле метода. Такие исключения принято называть проверяемыми. В Java предусмотрен также ряд других исключений, определения которых содержатся в различных библиотеках классов. К их числу можно отнести упоминавшееся ранее исключение IOException.

Таблица 9.2. Непроверяемые исключения, определенные в пакете java.lang Исключение Описание ArithmeticException Арифметическая ошибка, например попытка деления на нуль ArraylndexOutOfBoundsException Попытка обращения за границы массива ArrayStoreException Попытка ввести в массив элемент, несовместимый с ним по типу ClassCastException Недопустимое приведение типов EnumConstNotPresentException Попытка использования нумерованного значения, которое не было определено ранее IllegalArgumentException Недопустимый параметр при вызове метода IllegalMonitorStateException Недопустимая операция контроля, например, ожидание разблокировки потока IllegalStateException Недопустимое состояние среды выполнения или приложения IllegalThreadStateException Запрашиваемая операция несовместима с текущим состоянием потока IndexOutOfBoundsException Недопустимое значение индекса NegativeArraySizeException Создание массива отрицательного размера NullPointerException Недопустимое использование пустой ссылки NumberFormatException Неверное преобразование символьной строки в число SecurityException Попытка нарушить систему защиты StringlndexOutOfBounds Попытка обращения к символьной строке за ее границами TypeNotPresentException Неизвестный тип UnsupportedOperationException Неподдерживаемая операция

Таблица 9.3. Проверяемые исключения, определенные в пакете java.lang Исключение Описание ClassNotFoundException Класс не найден CloneNotSupportedException Попытка клонирования объекта, не реализующего интерфейс Cloneable IllegalAccessException Доступ к классу запрещен InstantiationException Попытка создания объекта абстрактного класса или интер¬фейса InterruptedException Прерывание одного потока другим NoSuchFieldException Требуемое поле не существует NoSuchMethodException Требуемый метод не существует ReflectiveOperationException Суперкласс исключений, связанных с рефлексией (добавлен в версии JDK 7) Создание подклассов, производных от класса Exception

Несмотря на то что встроенные в Java исключения позволяют обрабатывать большинство ошибок, механизм обработки исключений не ограничивается только этими ошибками. В частности, можно создавать исключения для обработки потенциальных ошибок в прикладной программе. Создать исключение несложно. Для этого достаточно определить подкласс, производный от класса Exception, который, в свою очередь, является подклассом,

порожденным классом Throwable. В создаваемый подкласс не обязательно включать реализацию каких-то методов. Сам факт существования такого подкласса позволяет использовать его в качестве исключения.

В классе Exception не определены новые методы. Он лишь наследует методы, предоставляемые классом Throwable. Таким образом, все исключения, включая и создаваемые вами, содержат методы класса Throwable. Конечно же, вы вольны переопределить в создаваемом вами классе один или несколько методов.

Ниже приведен пример, в котором создается исключение NonlntResultException. Оно генерируется в том случае, если результатом деления двух целых чисел является дробное число. В классе NonlntResultException содержатся два поля, предназначенные для хранения целых чисел, а также конструктор. В нем также переопределен метод toString , что дает возможность выводить описание исключения с помощью метода println. // Применение специально создаваемого исключения. // создать исключение class NonlntResultException extends Exception { int n; int d; NonlntResultException(int i, int j) { n = i; d = j; } public String toString { return "Result of " + n + " / " + d + " is non-integer."; } } class CustomExceptDemo { public static void main(String args[]) { // В массиве numer содержатся нечетные числа, int numer[] = { 4, 8, 15, 32, 64, 127, 256, 512 }; int denom[] = { 2, 0, 4, 4, 0, 8 }; for(int i=0; i<numer.length; i++) { try { if((numer[i]%2) != 0) throw new NonlntResultException(numer[i], denom[i]); System.out.println(numer[i] + " / " + denom[i] + 11 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."); } catch (NonlntResultException exc) { System.out.println(exc) ; } } } }

Результат выполнения данной программы выглядит следующим образом: 4 / 2 is 2 Can't divide by Zero! Result of 15 / 4 is non-integer. 32 / 4 is 8 Can't divide by Zero! Result of 127 / 8 is non-integer. No matching element found. No matching element found.

Пример для опробования 9.1. Добавление исключений в класс очереди

В этом проекте предстоит создать два класса исключении, которые будут использоваться классом очереди, разработанным в примере для опробования 8.1. Эти исключения должны указывать на переполнение и опустошение очереди, а генерировать их будут методы put и get соответственно. Ради простоты эти исключения добавляются в класс FixedQueue, но вы можете без труда внедрить их в любые другие классы очереди, разработанные в примере для опробования 8.1.

Последовательность действий

Создайте файл QExcDemo.java.

Определите следующие исключения в файле QExcDemo.java: /* Пример для опробования 9.1. Добавление обработчиков исключений в класс очереди. */ // Исключение, указывающее на переполнение очереди, class QueueFullException extends Exception { int size; QueueFullException(int s) { size = s; } public String toString { return "\nQueue is full. Maximum size is " + size; } } // Исключение, указывающее на опустошение очереди, class QueueEmptyException extends Exception { public String toString { return "\nQueue is empty."; } }

Исключение QueueFullException генерируется при попытке поместить элемент в уже заполненную очередь, а исключение QueueEmptyException — в ответ на попытку извлечь элемент из пустой очереди.

Измените класс FixedQueue таким образом, чтобы при возникновении ошибки он генерировал исключение. Соответствующий код приведен ниже. Введите этот код в файл QExcDemo.java. // Класс, реализующий очередь фиксированного размера // для хранения символов. class FixedQueue implements ICharQ { private char q[]; // Массив для хранения элементов очереди, private int putloc, getloc; // Индексы размещения и извлечения // элементов очереди. // создать пустую очередь заданного размера public FixedQueue(int size) { q = new char[size+1]; // выделить память для очереди putloc = getloc = 0; } // поместить символ в очередь public void put(char ch) throws QueueFullException { if(putloc==q.length-1) throw new QueueFullException(q.length-1); putloc++; q[putloc] = ch; } // извлечь символ из очереди public char get throws QueueEmptyException { if(getloc == putloc) throw new QueueEmptyException; getloc++; return q[getloc]; } }

Добавление исключений в класс FixedQueue выполняется в два этапа. Сначала в определении методов get и put указывается оператор throws с типом генерируемого исключения. А затем в этих методах организуется генерирование исключений при возникновении ошибок. Используя исключения, можно организовать обработку ошибок в вызывающей части программы наиболее рациональным способом. Как вы помните, в предыдущих версиях рассматриваемой здесь программы выводились только сообщения об ошибках. А генерирование исключений является более профессиональным подходом к разработке данной программы.

Поделиться с друзьями: