at Full Constructors g(Ful1 Constructors java:15) at FullConstructors.main(FullConstructors.java 24)
III-
Изменения незначительны — появилось два конструктора, определяющие способ создания объекта MyException. Во втором конструкторе используется конструктор родительского класса с аргументом String, вызываемый ключевым словом super.
В обработчике исключений вызывается метод printStackTrace() класса Throwable (базового для Exception). Этот метод выводит информацию о последо¬вательности вызовов, которая привела к точке возникновения исключения. В нашем примере информация направляется в System.out, но вызов по умолча¬нию направляет информацию в стандартный поток ошибок:
e.printStackTraceO,
Регистрация исключений
Вспомогательное пространство имен java.utiLlogging позволяет зарегистриро¬вать информацию об исключениях в журнале. Базовые средства регистрации достаточно просты:
II exceptions/LoggingExceptions.java // Регистрация исключений с использованием Logger import java.util.logging *; import java.io *;
class LoggingException extends Exception { private static Logger logger =
Logger getLogger("LoggingException"); public LoggingException() {
StringWriter trace = new StringWriter(); printStackTrace(new PrintWriter(trace)), 1ogger.severe(trace.toStri ng()),
public class LoggingExceptions {
public static void main(String[] args) { try {
throw new LoggingException(); } catch(LoggingException e) {
System.err.println("Перехвачено " + e),
}
try {
throw new LoggingExceptionO: } catch(LoggingException e) {
System.err.println("Перехвачено " + e),
} /* Output (85Х match)
Aug 30, 2005 4:02:31 РМ LoggingException <init> SEVERE LoggingException
at LoggingExceptions.main(LoggingExceptions.java:19)
Перехвачено LoggingException
Aug 30, 2005 4.02.31 PM LoggingException <init>
SEVERE LoggingException
at Loggi ngExcepti ons.mai n(Loggi ngExcepti ons.j ava:24)
Перехвачено LoggingException */// -
Статический метод Logger.getLogger() создает объект Logger, ассоциируемый с аргументом String (обычно имя пакета и класса, к которому относятся ошиб¬ки); объект передает свой вывод в System.err. Простейший способ записи ин¬формации в Logger заключается в вызове метода, соответствующего уровню ошибки; в нашем примере используется метод severe(). Нам хотелось бы создать String для регистрируемого сообщения из результатов трассировки стека, но ме¬тод printStackTrace() по умолчанию не создает String. Для получения String необ¬ходимо использовать перегруженную версию printStackTrace() с аргументом java.io.PrintWriter (за подробными объяснениями обращайтесь к главе «Ввод/вы¬вод»). Если передать конструктору PrintWriter объект java.io. StringWriter, для по¬лучения вывода в формате String достаточно вызвать toString().
Подход LoggingException чрезвычайно удобен (вся инфраструктура регистра¬ции встроена в само исключение, и все работает автоматически без вмешательст¬ва со стороны клиента), однако на практике чаще применяется перехват и реги¬страция «сторонних» исключений, поэтому сообщение должно генерироваться в обработчике исключения:
//: exceptions/LoggingExceptions2.java // Регистрация перехваченных исключений, import java.util.logging.*; import java.io.*:
public class LoggingExceptions2 { private static Logger logger =
Logger.getLogger("Loggi ngExcepti ons2"): static void logException(Exception e) {
StringWriter trace = new StringWriter(); e.printStackTrace(new PrintWriter(trace)): 1ogger.severe(trace.toStri ng());
}
public static void main(String[] args) { try {
throw new NullPointerException(); } catch(NullPointerException e) { logException(e):
}
}
} /* Output: (90* match)
Aug 30, 2005 4:07:54 PM LoggingExceptions2 logException
SEVERE: java.lang.NullPointerException продолжение &
at LoggingExceptions2 main(LoggingExceptions2 java:16)
*///.-
На этом процесс создания собственных исключений не заканчивается — ис¬ключение можно снабдить дополнительными конструкторами и элементами:
//: exceptions/ExtraFeatures.java // Дальнейшее расширение классов исключений, import static net.mindview.util.Print.*:
class MyException2 extends Exception { private int x; public MyException2() {} public MyException2(String msg) { super(msg): } public MyException2(String msg, int x) { super(msg): this.x = x:
}
public int valО { return x: } public String getMessageO {
return "Подробное сообщение: "+ x + " " + super getMessageO:
public class ExtraFeatures {
public static void f() throws MyException2 { print("MyException2 в f()"), throw new MyException2():
}
public static void g() throws MyException2 {
System out.println("MyException2 в g()"); throw new MyException2("Возбуждено в g()");
}
public static void h() throws MyException2 {
System out.println("MyException2 в h()"): throw new MyException2("Возбуждено в h()", 47);
}
public static void main(String[] args) { try {
f():
} catch(MyException2 e) {
e.printStackTrace(System.out);
}
try {
g():
} catch(MyException2 e) {
e.printStackTrace(System out):
}
try {
h():
} catch(MyException2 e) {
e.printStackTrace(System.out):
System out.printlnC'e.valO = " + e.valO):
}
}
} /* Output: MyException2 в f()
MyException2: Подробное сообщение: 0 null
at ExtraFeatures.f(ExtraFeatures.java•22)
at ExtraFeatures.main(ExtraFeatures.java.34) MyException2 в g()
MyException2: Подробное сообщение: 0 Возбуждено в g()
at ExtraFeatures.g(ExtraFeatures.java:26) at ExtraFeatures.main(ExtraFeatures.java:39) MyException2: Подробное сообщение: 47 Возбуждено в h() at ExtraFeatures.h(ExtraFeatures.java:30) at ExtraFeatures.main(ExtraFeatures.java:44)
e.valO = 47 *///:-
Было добавлено поле данных х вместе с методом, считывающим его значе¬ние, а также дополнительный конструктор для инициализации х. Переопреде¬ленный метод Throwable.getMessage() выводит более содержательную информа¬цию об исключении. Метод getMessage() для классов исключений — аналог toStringO в обычных классах.
Так как исключение является просто видом объекта, расширение возможно¬стей классов исключений можно продолжить. Однако следует помнить, что все эти программисты, использующие ваши библиотеки, могут попросту проигно¬рировать все «украшения» — нередко программисты ограничиваются провер¬кой типа исключения (как чаще всего бывает со стандартными исключениями Java).
Спецификации исключений
В языке Java желательно сообщать программисту, вызывающему ваш метод, об исключениях, которые данный метод способен возбуждать. Пользователь, вызывающий метод, сможет написать весь необходимый код для перехвата воз¬можных исключений. Конечно, когда доступен исходный код, программист- клиент может пролистать его в поиске предложений throw, но библиотеки не всегда поставляются с исходными текстами. Чтобы библиотека не превраща¬лась в «черный ящик», в Java добавили синтаксис (обязательный для использо¬вания), при помощи которого вы сообщаете клиенту об исключениях, возбуж¬даемых методом, чтобы он сумел правильно обработать их. Этот синтаксис называется спецификацией исключений (exception specification), входит в объяв¬ление метода и следует сразу за списком аргументов.
Спецификация исключений состоит из ключевого слова throws, за которым перечисляются все возможные типы исключений. Примерное определение ме¬тода будет выглядеть так:
void f() throws TooBig. TooSmall. DivZero { //...
Однако запись
void f() { // ...
означает, что метод не вырабатывает исключений. (Кроме исключений, произ¬водных от RuntimeException, которые могут быть возбуждены практически в лю¬бом месте — об этом еще будет сказано.)