Урок 10. Обработка исключений в Java ( Часть 1 )
В этой главе обсуждаетсяиспользуемый в 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 в результате возникновения определенных исключительных состояний.Например, очередная наша программа содержит выражение, при вычислении котороговозникает деление на нуль.
classExc0{
publicstatic void main(string args[]) {
intd = 0-
inta = 42 / d-
} }
Вот вывод, полученный при запуске нашего примера.
С:\->- java Exc0
java.lang.ArithmeticException:/ by zero
atExc0.main(Exc0.java:4)
Обратите внимание на тот факт чтотипом возбужденного исключения был не Exception и не Throwable. Это подкласскласса Exception, а именно: ArithmeticException, поясняющий, какая ошибкавозникла при выполнении программы. Вот другая версия того же класса, в которойвозникает та же исключительная ситуация, но на этот раз не в программном кодеметода main.
classExc1 {
staticvoid subroutine() {
intd = 0-
inta = 10 / d-
}
publicstatic void main(String args[]) {
Exc1.subroutine()-
}}
Вывод этой программы показывает, как обработчик исключенийисполняющей системы Java выводит содержимое всего стека вызовов.
С:\->- java Exc1
java.lang.ArithmeticException:/ by zero
atExc1.subroutine(Exc1.java:4)
atExc1.main(Exc1.java:7)
try и catch
Для задания блока программного кода, который требуетсязащитить от исключений, используется ключевое слово try. Сразу же послеtry-блока помещается блок catch, задающий тип исключения которое вы хотитеобрабатывать.
classExc2 {
publicstatic void main(String args[]) {
try{
intd = 0-
inta = 42 / d-
}
catch(ArithmeticException e) {
System.out.println(«divisionby zero»)-
}
} }
Целью большинства хорошосконструированных catch-разделов должна быть обработка возникшей исключительнойситуации и приведение переменных программы в некоторое разумное состояние —такое, чтобы программу можно было продолжить так, будто никакой ошибки и небыло (в нашем примере выводитсяпредупреждение – division by zero).
Несколько разделов catch
В некоторых случаях один и тот же блок программного кодаможет возбуждать исключения различных типов. Для того, чтобы обрабатыватьподобные ситуации, Java позволяет использовать любое количество catch-разделовдля try-блока. Наиболее специализированные классы исключений должны идтипервыми, поскольку ни один подкласс не будет достигнут, если поставить его послесуперкласса. Следующая программа перехватывает два различных типа исключений,причем за этими двумя специализированными обработчиками следует раздел catchобщего назначения, перехватывающий все подклассы класса Throwable.
classMultiCatch {
publicstatic void main(String args[]) {
try{
inta = args.length-
System.out.println(«a = » +a)-
int b = 42 / a-
int c[] = { 1 }-
c[42] = 99-
}
catch(ArithmeticException e) {
System.out.println(«divby 0: » + e)-
}
catch(ArrayIndexOutOfBoundsExceptione) {
System.out.println(«arrayindex oob: » + e)-
}
}}
Этот пример, запущенный без параметров, вызываетвозбуждение исключительной ситуации деления на нуль. Если же мы зададим вкомандной строке один или несколько параметров, тем самым установив а в значениебольше нуля, наш пример переживет оператор деления, но в следующем операторебудет возбуждено исключение выхода индекса за границы массива ArrayIndexOutOfBounds. Ниже приведены результаты работы этой программы, запущенной и тем идругим способом.
С:\->- java MultiCatch
а= 0
divby 0: java.lang.ArithmeticException: / by zero
arrayindex oob: java.lang.ArrayIndexOutOfBoundsException:42
Вложенные операторы try
Операторы try можно вкладывать друг в друга аналогичнотому, как можно создавать вложенные области видимости переменных. Если уоператора try низкого уровня нет раздела catch, соответствующего возбужденномуисключению, стек будет развернут на одну ступень выше, и в поисках подходящегообработчика будут проверены разделы catch внешнего оператора try. Вот пример, вкотором два оператора try вложены друг в друга посредством вызова метода.
classMultiNest {
staticvoid procedure() {
try{
int c[] = { 1 }-
c[42] = 99-
}
catch(ArrayIndexOutOfBoundsExceptione) {
System.out.println(«arrayindex oob: » + e)-
}}
publicstatic 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(«divby 0: » + e)-
}
}}