WebClub - Всероссийский Клуб Веб-разработчиков
WebClub.RU » Архив » Обработка исключений.

Обработка исключений.


Дата публикации: 17-03-2013

ИСКЛЮЧИТЕЛЬНЫЕ СИТУАЦИИ И ИХ ОБРАБОТКА

Как и всё в Java, исключительные ситуации (исключения, exceptions) есть объекты, или вернее сказать, исключительные ситуации порождают объекты определенного класса: java.lang.Throwable.


Какие бывают исключения и что с ними делать?

Исключения можно разделить на три категории, каждая из которых требует определенного подхода к их обработке (об обработке см. далее). Класс Errors и его подклассы: эти исключения порождаются при таких ошибках, которые программа не может обработать сама и при возникновении которых программа не может быть продолжена в любом случае, например нехватка памяти, ошибки виртуальной машины и т. п. Компилятор не требует, чтобы в программе были предусмотрены специальные меры по обработке исключений этого класса (иначе говоря не требуется обработки исключений этого класса). Причина такого "нетребования" заключается в том, что такие ошибки могут во зникнуть в любом месте программы (точнеее - в любой момент) и они практически не зависят от программиста. Класс RuntimeException: Такие исключения хоть и являются следствием ошибок логики программы, тем не менее также не требуют обработки (хотя и могут обрабатываться!). Причина: тривиальность такого рода ошибок - такие исключения могут появиться в слишком мн огих местах программы, чтобы предусматривать их возникновение - проще предусмотреть их невозникновение, т.е. написать программу без ошибок. Например, исключение NullPointerException может возникнуть при каждом обращении к какой-либо переменной типа ссылк и на объект, но предусматривать в каждом случае возникновение такого исключения слишком накладно, проще написать программу так, чтобы до такого обращения ссылка имела определенное (не null) значение или уж сделать простейшую проверку типа if (obj!=null) ia?aa ia?auaieai e nnueea. И наконец, класс Exception и его потомки, за исключением RuntimeException с его потомками: такие исключения могут возникать и в "правильной" программе, а их возникновение не зависит от программиста. Например, если в программе предусмотрена работа с файл ами, то в любой момент, когда файл открывается, читается или в него пишется, может произойти исключение класса IOException. Если не предусмотреть его обработку, то "рухнет" вся программа, хотя ошибка не столь серьезна и можно было продолжить программу да же и при её возникновении. Поэтому компилятор требует обрабатывать такие исключения (называемые так же Checked Exception).

Как узнать, необходимо ли обрабатывать при вызове данного метода какое либо исключение и какое именно?

Если вы используете метод какого-нибудь класса из стандартной библиотеки классов, то посмотрите на описание метода в документации - если после описания метода стоит ключевое слово throws и затем имя класса-исключения, то это означает, что вы обязаны пред усмотреть обработку этого исключения. Например: в классе java.io.BufferedInputStream метод read описан след. образом:
public synchronized int read() throws IOException
Следует предусмотреть обработку IOException. Если вы забудете это сделать, компилятор вас предупредит. А в классе java.lang.Math метоl pow описан так:
public static native double pow(double a, double b)
Здесь специально обрабатывать никаких исключений не надо, но в описании метода можно заметить, что метод всё же может породить исключение класса ArithmeticException (подкласс RuntimeException), при необходимости можно предусмотреть его обработку, но это не обязательно.

Как обрабатывать исключения?

Обработать исключительную ситуацию означает:
1) предусмотреть возможность её возникновения;
2) предусмотреть в программе специальные действия при её возникновении.
Эти два пункта реализуются специальной конструкцией языка Java, называемой try - catch, при этом try реализует пункт 1), а catch - пункт 2)
Например:
try {
// Здесь следует код, который может породить исключение IOException
} catch(IOException e) { //Обработка исключения
System.out.println("Ошибка ввода-вывода: "+e.getMessage())
}

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

Как будет работать программа, в которой есть блоки try-catch-finally?

Рассмотрим три случая:
1) Исключение произошло вне блока try:
· исполнение метода прерывается с той точки, где произошло исключение
· исключение передается в тот метод, который вызвал данный метод
· если в вызывающем методе этот вызов не находится в блоке try, то исполнение метода также прерывается и исключение "выталкивается" наверх, в метод, который вызвал этот метод
· это происходит до тех пор, пока исключение не достигнет самого верхнего метода, после чего исключение передается операционной системе, а программа прекращает работу.

2) Исключение произошло в блоке try:
· исполнение метода прерывается с той точки, где произошло исключение
· выполняется блок catch
· выполняется блок finally
· исполнение метода на этом прекращается, и передается в вызывающий метод
· далее программа продолжает работу

3) Никакого исключения не произошло:
· исполняется весь метод, за исключением блока catch
· блок finally также исполняется

Как породить исключение собственного типа?

Как обычно: создаем собственное исключение - класс, наследующий java.lang.Throwable. Например, MyException
В точку программы, где, по нашему мнению, должно возникнуть наше исключение, вставляем выражение throw new MyException("Произошло исключение!");
Учтите, что компилятор потребует заключить этот код в блок try.
Можно поступить проще - воспользоваться уже готовым классом-исключением, например IOException или лучше просто Exception (тогда не надо будет импортировать библиотеку классов java.io).
Следующие примеры демонстрируют применение обоих подходов:

public class MyExcept {
public static void main(String arg[]) {
try {
for (int i=0; i20) throw new MyException("i reached 21!!!");
}
} catch(MyException me) {System.out.println(me.getMessage());}
}
}

class MyException extends Throwable {
MyException(String s) {
super(s);
}
}


public class MyExcept {
public static void main(String arg[]) {
try {
for (int i=0; i20) throw new Exception("i reached 21!!!");
}
} catch(Exception e) { System.out.println(e.getMessage()); }
}
}

Обработка исключений методом "выталкивания".

Рассмотрим следующий пример:

public class MyExcept {
public static void main(String arg[]) {
try {
dangerous();
} catch(Exception me) { System.out.println(me.getMessage()); }
}

public static void dangerous() throws Exception {
for (int i=0; i20) throw new Exception("i reached 21!!!");
}
}
}

Как видим, код, который может вызвать исключение, не заключен в блок try, но зато весь метод объявлен как "выбрасывающий" (throws) исключение. Теперь это исключение можно поймать и обработать в том месте, где мы вызвали метод dangerous - в методе main, а не непосредственно в методе dangerous. Зачем нужна такая техника? Иногда бывает удобно обрабатывать исключения "скопом", в одном месте программы, например, когда методов много, и все они содержат потенциально "опасный" код. Применяя эту методику можно п ередавать, или, как говорят, "выталкивать" исключения наверх по цепочке любой длины и "ловить" их в удобном месте.

"Overriding" методов, выбрасывающих исключения.

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

Например:

import java.io.*;

public class MyExcept1 {
void method() throws Exception {
for (int i=0; i20) throw new Exception("i reached 21!!!");
}
}
}

class MyExcept2 extends MyExcept1 {
void method() throws IOException { //Метод выбрасывает исключение
//подкласса Exception
for (int i=0; i20) throw new IOException("i reached 21!!!");
}
}
}

class MyExcept3 extends MyExcept1 {
void method() { //Метод не выбрасывает никакого
//исключения, но зато обрабатывает
try { //его сам
for (int i=0; i20) throw new Exception("i reached 21!!!");
}
} catch(Exception e) { System.out.println(e.getMessage()); }
}
}

Андрей Дуглас 1998г.

Популярное

Не так давно в сети появился новый сервис, под названием Dead Man Zero. Этот сервис сделал...
Рынок социальных площадок уже давно стал стабильным. Несмотря на то, что время от времени...
Artisteer 4 – единственный в своем роде продукт, позволяющий автоматизировать работу над созданием...
Март 2017 (1)
Февраль 2017 (3)
Январь 2017 (1)
Август 2016 (1)
Май 2016 (2)
Ноябрь 2015 (1)

Карта сайта: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41

Друзья сайта

Хотите продать свой сайт?
- Мы быстро и удобно для Вас сможем его купить:
  • Заявка на продажу сайта
  • Раcсматриваем цены на каждый сайт в индивидуальном порядке.

    Случайная цитата

    Linus Torvalds:

    "Болтовня ничего не стоит. Покажите мне код."

    Опрос

    Какой аудио плеер Вы используете?

    Winamp
    Light Alloy
    foobar2000
    Apollo
    AIMP
    1by1
    iTunes
    jetAudio
    Другой...