Создание собственных подклассов исключений
Встроенные исключения языка Java обрабатывают наиболее общие ошибки. Существует возможность создавать свои собственные типы исключений с целью обработки ситуаций, специфических для ваших приложений. Для этого определите подкласс Exception. Созданные подклассы не должны ничего реализовывать — само существование их в системе типов позволяет использовать их как исключения.
Класс Exception не определяет никаких собственных методов, а наследует эти методы от класса Throwable. Таким образом, всем исключениям, даже тем, что вы создаете сами, доступны методы Throwable. Список их представлен в табл. ниже. Кроме того, вы можете переопределить один или несколько этих методов в создаваемых вами классах исключений.
Метод |
Описание |
Throwable fillInStackTrace() |
Возвращает Throwable-объект, который содержит полную трассу стека. Этот объект может быть выброшен повторно |
String getLocalizedMessage() |
Возвращает локализованное описание исключения |
String getMessage() |
Возвращает описание исключения |
void printStackTrace() |
Отображает трассу стека |
String toString() |
Возвращает string-объект, содержащий описание исключения. Этот метод вызывается из println() при выводе Throwable-объекта |
Следующий пример объявляет новый подкласс Exception и затем использует его, чтобы сигнализировать об аварийной ситуации в методе. Он переопределяет метод toString(), позволяя отобразить описание исключения с помощью println().
// Эта программа создает заказной тип исключения.
class MyException extends Exception {
private int detail;
MyException(int a) {
detail = a;
}
public String toString() {
return "MyException[" + detail + "]";
}
}
class ExceptionDemo {
static void compute(int a) throws MyException {
System.out.println("Вызван compute(" + a + ")");
if(a > 10) throw new MyException(a);
System.out.println("Нормальный выход");
}
public static void main(String args[]) {
try {
compute(1);
compute(20);
} catch (MyException e) {
System.out.println("Вброшено " + e);
}
}
}
Этот пример определяет подкласс Exception с именем MyException. Этот подкласс весьма прост — он имеет только конструктор и перегруженный метод toString(), который отображает значение исключения. Класс ExceptionDemo определяет метод, названный compute(), который выбрасывает объект MyException. Исключение выбрасывается, когда целый параметр метода computed больше 10. Метод main о устанавливает обработчик исключений для MyException, а затем вызывает compute() с допустимым значением параметра (меньшим 10) и недопустимым, чтобы показать оба варианта работы программы. Вот результат:
Вызван compute(1)
Нормальный выход
Вызван compute(20)
Выброшено MyException[20]
Как использовать исключительные ситуации
Обычно исключительные ситуации применяют слишком часто.
1. Обработка исключительных ситуаций не может заменить собой простую проверку.
Для иллюстрации мы написали фрагмент программы, использующей встроенный класс Stack. Программа, приведенная ниже, делает 1000000 попыток вытолкнуть элемент из пустого стека. Сначала она определяет, пуст ли стек.
if (!s.empty()) s.pop();
Затем мы заставляем ее выталкивать элемент из стека, не обращая внимания на то, что он пуст. После этого мы перехватываем исключительную ситуацию EmptyStackException, которая сообщает нам, что мы не правы.
try
{
s.pop();
}
catch(EmptyStackException e)
{
}
Текст программы:
/* @version 1.10 2000-06-03 @author Cay Horstmann */
import java.util.*;
public class ExceptionalTest
{
public static void main(String[] args)
{
int i = 0;
int ntry = 1000000;
Stack s = new Stack();
long s1;
long s2;
// ntry раз проверить пуст ли стек
System.out.println("Testing for empty stack");
s1 = new Date().getTime();
for (i = 0; i <= ntry; i++)
if (!s.empty()) s.pop();
s2 = new Date().getTime();
System.out.println((s2 - s1) + " milliseconds");
// ntry раз извлекается элемент из пустого стека
// и генерируется исключение
System.out.println("Catching EmptyStackException");
s1 = new Date().getTime();
for (i = 0; i <= ntry; i++)
{
try
{
s.pop();
}
catch(EmptyStackException e)
{
}
}
s2 = new Date().getTime();
System.out.println((s2 - s1) + " milliseconds");
}
}
Время, которое мы затратили на эти операции, равно соответственно 94 мс и 2422 мс.
Как видим, перехват исключительной ситуации занял намного больше времени, чем простая проверка. Используйте исключительные ситуации только в действительно исключительных обстоятельствах!
