Блоки перехвата исключения
Мы можем перехватить и обработать исключение в программе. При описании обработки применяется бейсбольная терминология. Говорят, что исполняющая система или программа "выбрасывает" (throws) объект-исключение. Этот объект "пролетает" через всю программу, появившись сначала в том методе, где произошло исключение, а программа в одном или нескольких местах пытается (try) его "перехватить" (catch) и обработать. Обработку можно сделать полностью в одном месте, а можно обработать исключение в одном месте, выбросить снова, перехватить в другом месте и обрабатывать дальше.
Мы уже много раз в этой книге сталкивались с необходимостью обрабатывать различные исключительные ситуации, но не делали этого, потому что не хотели отвлекаться от основных конструкций языка. Не вводите это в привычку! Хорошо написанные объектно-ориентированные программы обязательно должны обрабатывать все возникающие в них исключительные ситуации.
Для того чтобы попытаться (try) перехватить (catch) объект-исключение, надо весь код программы, в котором может возникнуть исключительная ситуация, охватить оператором try{} catch () {}. Каждый блок catch() {} перехватывает исключение только одного типа, того, который указан в его аргументе. Но можно написать несколько блоков catch(){} для перехвата нескольких типов исключений.
Например, мы знаем, что в программе листинга 16.1 могут возникнуть исключения двух типов. Напишем блоки их обработки, как это сделано в листинге 16.2.
Листинг 16.2. Программа с блоками обработки исключений.
class SimpleExtlf public static void main(String[] args){ try{ int n = Integer.parselnt(args[0]); System.out.println("After parselnt()); System.out.println(" 10 / n = " + (10 / n)); Systfem .out .println ("After results output"); }catch(ArithmeticException ae){ System.out.println("From Arithm.Exc .catch: "+ae); }catch(ArraylndexOutOfBoundsException arre){ System.out.println("From Array.Exc.catch: "+arre); }finally{ System.out.println("From finally"); } System.out.println("After all actions"); } }
В программу листинга 16.1 вставлен блок try{} и два блока перехвата catch(){} для каждого типа исключений. Обработка исключения здесь заключается просто в выводе сообщения и содержимого объекта-исключения, как оно представлено методом tostring() соответствующего класса-исключения.
После блоков перехвата вставлен еще один, необязательный блок finaliy(). Он предназначен для выполнения действий, которые надо выполнить обязательно, чтобы ни случилось. Все, что написано в этом блоке, будет выполнено и при возникновении исключения, и при обычном ходе программы, и даже если выход из блока try{} осуществляется оператором return.
Если в операторе обработки исключений есть блок finally{}, то блок catch () {} может отсутствовать, т. е. можно не перехватывать исключение, но при его возникновении все-таки проделать какие-то обязательные действия.
Кроме блоков перехвата в листинге 16.2 после каждого действия делается трассировочная печать, чтобы можно было проследить за порядком выполнения программы. Программа запущена три раза: с аргументом 5, с аргументом 0 и вообще без аргумента. Результат показан на рис. 16.2.