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

Атомная энергетика. Ядерные реакторы АЭС. Атомный флот. Ядерное оружие

РБМК-1000
Гражданский суда
Авиация

Высшая математика

Задачи
Практикум
Карта сайта

 

 

Глава 10 - Обработка исключений

В этой главе обсуждается используемый в Java механизм обработки исключений. Исключение в Java - это объект, который описывает исключительное состояние, воз-никшее в каком-либо участке программного кода. Когда возникает ис-ключительное состояние, создается объект класса Exception. Этот объект пересылается в метод, обрабатывающий данный тип исключительной ситуации. Исключения могут возбуждаться и <вруч-ную> для того, чтобы сообщить о некоторых нештатных ситуациях.

Основы

К механизму обработки исключений в Java имеют отношение 5 клю-чевых слов: - try, catch, throw, throws и finally. Схема работы этого механизма следующая. Вы пытаетесь (try) выполнить блок кода, и если при этом возникает ошибка, система возбуждает (throw) исключение, ко-торое в зависимости от его типа вы можете перехватить (catch) или пере-дать умалчиваемому (finally) обработчику.

Ниже приведена общая форма блока обработки исключений.

 try { // блок кода } catch (ТипИсключения1 е) { // обработчик исключений
типа ТипИсключения1 } catch (ТипИсключения2 е) { // обработчик исключений типа
ТипИсключения2 throw(e) // повторное возбуждение исключения } finally { }

Замечание

В языке Delphi вместо ключевого слова catch используется except.

Типы исключений

В вершине иерархии исключений стоит класс Throwable. Каждый из типов исключений является подклассом класса Throwable. Два непосредственных наследника класса Throwable делят иерархию подклассов исключений на две различные ветви. Один из них - класс Ехception - используется для описания исключительных ситуации, кото-рые должны перехватываться программным кодом пользователя. Другая ветвь дерева подклассов Throwable - класс Error, который предназначен для описания исклю-чительных ситуаций, которые при обычных условиях не должны перехватываться в пользовательской программе.

Неперехваченные исключения

Объекты-исключения автоматически создаются исполняющей средой Java в результате возникновения определенных исключительных состо-яний. Например, очередная наша программа содержит выражение, при вычислении которого возникает деление на нуль.

 class Exc0 { public static
void main(string args[]) { int d = 0; int a = 42 / d; } }

Вот вывод, полученный при запуске нашего примера.

 С:\> java Exc0 java.lang.ArithmeticException:
/ by zero at Exc0.main(Exc0.java:4)

Обратите внимание на тот факт что типом возбужденного исклю-чения был не Exception и не Throwable. Это подкласс класса Exception, а именно: ArithmeticException, поясняющий, какая ошибка возникла при выполнении программы. Вот другая версия того же класса, в кото-рой возникает та же исключительная ситуация, но на этот раз не в про-граммном коде метода main.

 class Exc1 { static void subroutine() { int d = 0; int a = 10 / d; } public
static void main(String args[]) { Exc1.subroutine(); } }

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

 С:\> java Exc1 java.lang.ArithmeticException: / by
zero at Exc1.subroutine(Exc1.java:4) at Exc1.main(Exc1.java:7)

try и catch

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

 class
Exc2 { public static void main(String args[]) { try { int d = 0; int a = 42 /
d; } catch (ArithmeticException e) { System.out.println("division by zero"); }
} }

Целью большинства хорошо сконструированных catch-разделов долж-на быть обработка возникшей исключительной ситуации и приведение переменных программы в некоторое разумное состояние - такое, чтобы программу можно было продолжить так, будто никакой ошибки и не было (в нашем примере выводится предупреждение - division by zero).

Несколько разделов catch

В некоторых случаях один и тот же блок программного кода может воз-буждать исключения различных типов. Для того, чтобы обрабатывать по-добные ситуации, Java позволяет использовать любое количество catch-разделов для try-блока. Наиболее специализированные классы исключений должны идти первыми, поскольку ни один подкласс не будет достигнут, если поставить его после суперкласса. Следующая про-грамма перехватывает два различных типа исключений, причем за этими двумя специализированными обработчиками следует раздел catch общего назначения, перехватывающий все подклассы класса Throwable.

 class MultiCatch { public static void main(String args[]) { try { int a
= args.length; System.out.println("a = " + a); int b = 42 / a; int c[] = { 1 };
c[42] = 99; } catch (ArithmeticException e) { System.out.println("div by 0: "
+ e); } catch(ArrayIndexOutOfBoundsException e) { System.out.println("array index
oob: " + e); } } }

Этот пример, запущенный без параметров, вызывает возбуждение ис-ключительной ситуации деления на нуль. Если же мы зададим в командной строке один или несколько параметров, тем самым установив а в значение боль-ше нуля, наш пример переживет оператор деления, но в следующем опе-раторе будет возбуждено исключение выхода индекса за границы масси-ва ArrayIndexOutOf Bounds. Ниже приведены результаты работы этой программы, за-пущенной и тем и другим способом.

 С:\>
java MultiCatch а = 0 div by 0: java.lang.ArithmeticException: / by zero C:\>
java MultiCatch 1 a = 1 array index oob: java.lang.ArrayIndexOutOfBoundsException:
42

Вложенные операторы try

Операторы try можно вкладывать друг в друга аналогично тому, как можно создавать вложенные области видимости переменных. Если у оператора try низкого уровня нет раздела catch, соответствующего возбужденному исключению, стек будет развернут на одну ступень выше, и в поисках подходящего обработчика будут прове-рены разделы catch внешнего оператора try. Вот пример, в котором два оператора try вложены друг в друга посредством вызова метода.

 class MultiNest { static void procedure() { try { int c[] = { 1
}; c[42] = 99; } catch(ArrayIndexOutOfBoundsException e) { System.out.println("array
index oob: " + e); } } public static void main(String args[]) { try { int a =
args.length(); System.out.println("a = " + a); int b = 42 / a; procedure(); }
catch (ArithmeticException e) { System.out.println("div by 0: " + e); } } }

throw

Оператор throw используется для возбуждения исключения <вруч-ную>. Для того, чтобы сделать это, нужно иметь объект подкласса клас-са Throwable, который можно либо получить как параметр оператора catch, либо создать с помощью оператора new. Ниже приведена общая форма оператора throw.

throw ОбъектТипаThrowable;

При достижении этого оператора нормальное выполнение кода немед-ленно прекращается, так что следующий за ним оператор не выполня-ется. Ближайший окружающий блок try проверяется на наличие соот-ветствующего возбужденному исключению обработчика catch. Если такой отыщется, управление передается ему. Если нет, проверяется следующий из вложенных операторов try, и так до тех пор пока либо не будет най-ден подходящий раздел catch, либо обработчик исключений исполняю-щей системы Java не остановит программу, выведя при этом состояние стека вызовов. Ниже приведен пример, в котором сначала создается объект-исключение, затем оператор throw возбуждает исключительную ситуацию, после чего то же исключение возбуждается повторно - на этот раз уже кодом перехватившего его в первый раз раздела catch.

 class ThrowDemo { static
void demoproc() { try { throw new NullPointerException("demo"); } catch (NullPointerException
e) { System.out.println("caught inside demoproc"); throw e; } } public static
void main(String args[]) { try { demoproc(); } catch(NulPointerException e) {
System.out.println("recaught: " + e); } } }

В этом примере обработка исключения проводится в два приема. Метод main создает контекст для исключения и вызывает demoproc. Метод demoproc также устанавливает контекст для обработки исключе-ния, создает новый объект класса NullPointerException и с помощью опе-ратора throw возбуждает это исключение. Исключение перехватывается в следующей строке внутри метода demoproc, причем объект-исключение доступен коду обработчика через параметр e. Код обработчика выводит сообщение о том, что возбуждено исключение, а затем снова возбуждает его с помощью оператора throw, в результате чего оно передается обра-ботчику исключений в методе main. Ниже приведен результат, получен-ный при запуске этого примера.

 С:\> java ThrowDemo caught inside demoproc recaught:
java.lang.NullPointerException: demo

throws

Если метод способен возбуждать исключения, которые он сам не об-рабатывает, он должен объявить о таком поведении, чтобы вызывающие методы могли защитить себя от этих исключений. Для задания списка исключений, которые могут возбуждаться методом, используется ключе-вое слово throws. Если метод в явном виде (т.е. с помощью оператора throw) возбуждает исключе-ние соответствующего класса, тип класса исключений должен быть ука-зан в операторе throws в объявлении этого метода. С учетом этого наш прежний синтаксис определения метода должен быть расширен следую-щим образом:

 тип имя_метода(список аргументов) throws список_исключений {}

Ниже приведен пример программы, в которой метод procedure пыта-ется возбудить исключение, не обеспечивая ни программного кода для его перехвата, ни объявления этого исключения в заголовке метода. Такой программный код не будет оттранслирован.

 class
ThrowsDemo1 { static void procedure() { System.out.println("inside procedure");
throw new IllegalAccessException("demo"); } public static void main(String args[])
{ procedure(); } }

Для того, чтобы мы смогли оттранслировать этот пример, нам при-дется сообщить транслятору, что procedure может возбуждать исключе-ния типа IllegalAccessException и в методе main добавить код для обработки этого типа исключений :

 class ThrowsDemo { static void procedure() throws IllegalAccessException
{ System.out.println(" inside procedure"); throw new IllegalAccessException("demo");
} public static void main(String args[]) { try { procedure(); } catch (IllegalAccessException
e) { System.out.println("caught " + e); } } }

Ниже приведен результат выполнения этой программы.

 С:\> java ThrowsDemo inside procedure caught
java.lang.IllegalAccessException: demo

finally

Иногда требуется гарантировать, что определенный участок кода будет выпол-няться независимо от того, какие исключения были возбуждены и пере-хвачены. Для создания такого участка кода используется ключевое слово finally. Даже в тех случаях, когда в методе нет соответствующего воз-бужденному исключению раздела catch, блок finally будет выполнен до того, как управление перейдет к операторам, следующим за разделом try. У каждого раздела try должен быть по крайней мере или один раз-дел catch или блок finally. Блок finally очень удобен для закрытия файлов и освобождения любых других ресурсов, захваченных для времен-ного использования в начале выполнения метода. Ниже приведен пример класса с двумя методами, завершение которых происходит по разным причинам, но в обоих перед выходом выполняется код раздела finally.

 class FinallyDemo { static void procA() { try { System.out.println("inside
procA"); throw new RuntimeException("demo"); } finally { System.out.println("procA's
finally"); } } static void procB() { try { System.out.println("inside procB");
return; } finally { System.out.println("procB's finally"); } } public static void
main(String args[]) { try { procA(); } catch (Exception e) {} procB(); } }

В этом примере в методе procA из-за возбуждения исключения про-исходит преждевременный выход из блока try, но по пути <наружу> вы-полняется раздел finally. Другой метод procB завершает работу выпол-нением стоящего в try-блоке оператора return, но и при этом перед выходом из метода выполняется программный код блока finally. Ниже приведен результат, полученный при выполнении этой программы.

 С:\>
java FinallyDemo inside procA procA's finally inside procB procB's finally

Подклассы Exception

Только подклассы класса Throwable могут быть возбуждены или пере-хвачены. Простые типы - int, char и т.п., а также классы, не являю-щиеся подклассами Throwable, например, String и Object, использоваться в качестве исключений не могут. Наиболее общий путь для использова-ния исключений - создание своих собственных подклассов класса Ex-ception. Ниже приведена программа, в которой объявлен новый подкласс класса Exception.

 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("called
computer+a+")."); if (a> 10) throw new MyException(a); System.out.println("normal
exit."); } public static void main(String args[]) { try { compute(1); compute(20);
} catch (MyException e) { System.out.println("caught" + e); } } }

Этот пример довольно сложен. В нем сделано объявление подкласса MyException класса Exception. У этого подкласса есть специальный кон-структор, который записывает в переменную объекта целочисленное значение, и совмещенный метод toString, выводящий значение, хранящееся в объекте-исключении. Класс ExceptionDemo определяет метод compute, который возбуждает исключение типа MyExcepton. Простая логика метода compute возбуждает исключение в том случае, когда значение пара-ветра метода больше 10. Метод main в защищенном блоке вызывает метод compute сначала с допустимым значением, а затем - с недопус-тимым (больше 10), что позволяет продемонстрировать работу при обоих путях выполнения кода. Ниже приведен результат выполнения програм-мы.

 С:\> java ExceptionDemo called compute(1). normal exit. called compute(20).
caught MyException[20]

Заключительное резюме

Обработка исключений предоставляет исключительно мощный меха-низм для управления сложными программами. Try, throw, catch дают вам простой и ясный путь для встраивания обработки ошибок и прочих нештатных ситуаций в программную логи-ку. Если вы научитесь должным об-разом использовать рассмотренные в данной главе механизмы, это при-даст вашим классам профессиональный вид, и любые будущие пользователи вашего программного кода, несомненно, оценят это.

7271f726
На главную