31

31


Основные исключения

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

от «обычных» ошибок, когда в текущем контексте имеется достаточно инфор¬мации для преодоления затруднений. В исключительной ситуации обработать исключение в текущем контексте невозможно, потому что вы не располагаете необходимой информацией. Остается единственный выход — покинуть теку¬щий контекст и передать проблему на более высокий уровень. Именно это и происходит при выдаче исключения.

Простейшим примером является деление. Потенциальное деление на нуль может быть выявлено проверкой соответствующего условия. Но что делать, если знаменатель оказался нулем? Возможно, в контексте текущей задачи из¬вестно, как следует поступить с нулевым знаменателем. Но, если нулевой зна¬менатель возник неожиданно, деление в принципе невозможно, и тогда необхо¬димо возбудить исключение, а не продолжать исполнение программы.

При возбуждении исключения происходит сразу несколько вещей. Во-пер- вых, создается объект, представляющий исключение, — точно так же, как и лю¬бой другой объект в Java (в куче, оператором new). Далее текущий поток испол¬нения (тот самый, где произошла ошибка) останавливается, и ссылка на объект, представляющий исключение, извлекается из текущего контекста. С этого мо¬мента включается механизм обработки исключений, который начинает поиск подходящего места программы для передачи исключения. Таким местом явля¬ется обработчик исключений, который пытается решить возникшую проблему так, чтобы программа могла снова попытаться выполнить проблемную опера¬цию или просто продолжила свое выполнение.

В качестве простого примера выдачи исключения представьте ссылку на объект t. Возможно, полученная вами ссылка не была инициализирована; стоит проверить это обстоятельство, прежде чем вызывать методы с использо¬ванием этой ссылки. Чтобы передать информацию об ошибке на более высо¬кий уровень, создайте объект, представляющий передаваемую информацию, и «запустите» его из текущего контекста. Тем самым вы возбудите исключение. Вот как это выглядит:

if(t — null)

throw new NullPointerException( );

Вырабатывается исключение, которое позволяет вам — в текущем контек¬сте — переложить с себя ответственность, не задумываясь о будущем. Ошибка, словно по волшебству, обрабатывается где-то в другом месте (вскоре мы узнаем, где именно).

Один из основополагающих аспектов исключений состоит в том, что при возникновении нежелательных ситуаций выполнение программы не продолжа¬ется по обычному пути. Исключения позволяют вам (в крайнем случае) остано¬вить программу и сообщить о возникших трудностях или (в идеале) разобрать¬ся с проблемой и вернуть программу в стабильное состояние.

Аргументы исключения

Исключения, как и любые объекты Java, создаются в куче оператором new, ко¬торый выделяет память и вызывает конструктор. У всех стандартных исключе¬ний существует два конструктора: стандартный (по умолчанию) и другой, со строковым аргументом, в котором можно разместить подходящую информа¬цию об исключении:

throw new NullPointerExceptionC't = null");

Переданная строка потом может быть извлечена различными способами, о чем будет рассказано позже.

Ключевое слово throw влечет за собой ряд довольно интересных действий. Как правило, сначала new используется для создания объекта, представляюще¬го условие происшедшей ошибки. Ссылка на указанный объект передается ко¬манде throw. Фактически этот объект «возвращается» методом, несмотря на то что для возвращаемого объекта обычно предусмотрен совсем другой тип. Та¬ким образом, упрощенно можно говорить об обработке исключений как об аль¬тернативном механизме возврата из исполняемого метода (впрочем, с этой ана¬логией не стоит заходить слишком далеко). Возбуждение исключений также позволяет выходить из простых блоков видимости. В обоих случаях возвраща¬ется объект исключения и происходит выход из текущего метода или блока.

Но все сходство с обычным возвратом из метода на этом заканчивается, по¬скольку при возврате из исключения вы попадаете совсем не туда, куда попали бы при нормальном вызове метода. (Обработчик исключения может находить¬ся очень «далеко» — на расстоянии нескольких уровней в стеке вызова — от ме¬тода, где возникла исключительная ситуация.)

Вообще говоря, можно возбудить любой тип исключений, происходящих от объекта Throwable (корневой класс иерархии исключений). Обычно для раз¬ных типов ошибок возбуждаются разные типы исключений. Информация о случившейся ошибке как содержится внутри объекта исключения, так и ука¬зывается косвенно в самом типе этого объекта, чтобы кто-то на более высоком уровне сумел выяснить, как поступить с исключением. (Нередко именно тип объекта исключения является единственно доступной информацией об ошибке, в то время как внутри объекта никакой полезной информации нет.)

Перехват исключений

Чтобы увидеть, как перехватываются ошибки, сначала следует усвоить понятие защищенной секции — той части программы, в которой могут произойти исклю¬чения и за которой следует специальный блок, отвечающий за обработку этих исключений.

Блок try

Если вы «находитесь» внутри метода и инициируете исключение (или это дела¬ет другой вызванный метод), этот метод завершит работу при возникновении исключения. Но если вы не хотите, чтобы оператор throw завершил работу ме¬тода, разместите в методе специальный блок для перехвата исключения — так называемый блок try. Этот блок представляет собой простую область действия, которой предшествует ключевое слово try:

try {

// Фрагмент, способный возбуждать исключения

}

Если бы не обработка исключений, для тщательной проверки ошибок вам пришлось бы добавить к вызову каждого метода дополнительный код для про¬верки ошибок — даже при многократном вызове одного метода. С обработкой исключений весь код размещается в блоке try, который и перехватывает все воз¬можные исключения в одном месте. А это означает, что вашу программу стано¬вится значительно легче писать и читать, поскольку выполняемая задача не сме¬шивается с обработкой ошибок.