Эккель Брюс
Шрифт:
Преобразование контролируемых исключений в неконтролируемые
Рассмотренный выше подход хорош при написании метода main, но в более общих ситуациях не слишком полезен. Подлинная проблема возникает при написании тела самого обычного метода, когда при вызове другого метода вы четко сознаете: «Понятия не имею, что делать с исключением дальше, но „съедать" мне его не хочется, так же как и печатать банальное сообщение». Проблема решается при помощи цепочек исключений. Управляемое исключение просто «заворачивается» в класс RuntimeException примерно так:
try {
// .. делаем что-нибудь полезное } са!сИ(НеЗнаюЧтоДелатьСЭтимКонтролируемымИсключением е) { throw new RuntimeException(e);
}
Решение идеально подходит для тех случаев, когда вы хотите «подавить» контролируемое исключение: вы не «съедаете» его, вам не приходится описывать его в своей спецификации исключений, и благодаря цепочке исключений вы не теряете информацию об исходном исключении.
Описанная методика позволяет игнорировать исключение и пустить его «всплывать» вверх по стеку вызова без необходимости писать блоки try-catch и (или) спецификации исключения. Впрочем, при этом вы все равно можете перехватить и обработать конкретное исключение, используя метод getCause, как показано ниже:
// exceptions/TurnOffChecking.java // "Подавление" контролируемых исключений, import java io *;
import static net mindview.util.Print.*;
class WrapCheckedException {
void throwRuntimeException(int type) { try {
switch(type) {
case 0: throw new FileNotFoundExceptionO; case 1: throw new IOExceptionO; case 2- throw new RuntimeExceptionCTfle Я?"). default: return;
}
} catch(Exception e) {
// Превращаем в неконтролируемое: throw new RuntimeException(e);
}
}
}
class SomeOtherException extends Exception {}
public class TurnOffChecking {
public static void main(String[] args) {
WrapCheckedException wee = new WrapCheckedExceptionO: // Можно вызвать throwRuntimeExceptionO без блока try, // и позволить исключению RuntimeException покинуть метод-wee. throwRuntimeExceptionO); // Или перехватить исключение: for (int i =0; i <4; i++) try {
if(i < 3)
wee throwRuntimeException(i);
else
throw new SomeOtherExceptionO: } catch(SomeOtherException e) {
print("SomeOtherException. " + e); } catch(RuntimeException re) {
try { продолжение &
throw re.getCauseO, } catch(FileNotFoundException e) {
print("FileNotFoundException. " + e); } catch(IOException e) {
print("IOException- " + e); } catch(Throwable e) {
print("Throwable. " + e);
}
}
}
} /* Output-
Fi1eNotFoundException: java.iо.Fi1eNotFoundException
IOException: java.io.IOException
Throwable: java.lang.RuntimeException. Где Я?
SomeOtherExcepti on: SomeOtherExcepti on
*///:-
Метод WrapCheckedException.throwRuntimeException содержит код, генерирующий различные типы исключений. Они перехватываются и «заворачиваются» в объекты RuntimeException, становясь таким образом «причиной» этих исключений.
При взгляде на класс TurnOffChecking нетрудно заметить, что вызвать метод throwRuntimeException можно и без блока try, поскольку он не возбуждает никаких контролируемых исключений. Но когда вы будете готовы перехватить исключение, у вас будет возможность перехватить любое из них — достаточно поместить свой код в блок try. Начинаете вы с перехвата исключений, которые, как вы знаете, могут явно возникнуть в коде блока try, — в нашем случае первым делом перехватывается SomeOtherException. В конце вы перехватываете Runtime-Exception и заново возбуждаете исключение, являющееся его причиной (получая последнее методом getCause, «завернутое» исключение). Так извлекаются изначальные исключения, обрабатываемые в своих предложениях catch.
Методика «заворачивания» управляемых исключений в объекты Runtime-Exception встречается в некоторых примерах книги. Другое возможное решение — создание собственного класса, производного от RuntimeException. Перехватывать такое исключение не обязательно, но, если вы захотите, такая возможность существует.
Основные правила обработки исключений
Используйте исключения для того, чтобы:
• обработать ошибку на текущем уровне (избегайте перехватывать исключения, если вы не знаете, как с ними поступить);
• исправить проблему и снова вызвать метод, возбудивший исключение;
• предпринять все необходимые действия и продолжить выполнение без повторного вызова метода;
• попытаться найти альтернативный результат вместо того, который должен был бы произвести вызванный метод;
• сделать все возможное в текущем контексте и заново возбудить это же исключение, перенаправив его на более высокий уровень;
• сделать все, что можно в текущем контексте, и возбудить новое исключение, перенаправив его на более высокий уровень;