Таблица 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 с типом генерируемого исключения. А затем в этих методах организуется генерирование исключений при возникновении ошибок. Используя исключения, можно организовать обработку ошибок в вызывающей части программы наиболее рациональным способом. Как вы помните, в предыдущих версиях рассматриваемой здесь программы выводились только сообщения об ошибках. А генерирование исключений является более профессиональным подходом к разработке данной программы.
Для опробования усовершенствованного класса FixedQueue введите в файл QExcDemo.java приведенный ниже исходный код класса QExcDemo. // Демонстрация исключений при обращении с очередью, class QExcDemo { public static void main(String args[]) { FixedQueue q = new FixedQueue(10); char ch; int i; try { // Переполнение очереди. for(i=0; i < 11; i++) { System.out.print("Attempting to store : " + (char) ('A' + i)); q.put((char) (fA' + i)); System.out.println(" - OK"); } System.out.println(); } catch (QueueFullException exc) { System.out.println(exc); } System.out.println(); try { // Попытка извлечь символ из пустой очереди. for(i=0; i < 11; i++) { System.out.print("Getting next char: "); ch = q.get(); System.out.println(ch); } } catch (QueueEmptyException exc) { System.out.println(exc); } } }