Обработка ошибок и исключения — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Как обрабатывать?)
Строка 3: Строка 3:
 
Исключениями или исключительными ситуациями (состояниями) называются ошибки, возникшие в программе во время её работы.
 
Исключениями или исключительными ситуациями (состояниями) называются ошибки, возникшие в программе во время её работы.
 
}}
 
}}
 +
Каждый раз, когда при выполнении программы происходит ошибка, создается объект-исключение, содержащий информацию об ошибке, включая её тип и состояние программы.
 +
После создания исключения (?) пытается найти в стеке вызовов метод, который содержит код, обрабатывающий это исключение. Поиск начинается с метода, в котором произошла ошибка, и проходит через стек в обратном порядке вызова методов. Если не было найдено ни одного подходящего обработчика, выполнение программы. завершается.
 +
 +
Таким образом, механизм обработки исключений содержит следующие операции:
 +
#Создание объекта-исключения.
 +
#Заполнение stack trace'а этого исключения.
 +
#Stack unwinding (раскрутка стека) в поисках нужного обработчика.
 
== Введение ==
 
== Введение ==
 
В языке <tex>Java</tex> исключения <tex>(Exceptions)</tex> и ошибки <tex>(Errors)</tex> являются объектами. Когда метод вызывает (бросает - throws) исключительную ситуацию, он на самом деле работает с объектом. Но такое происходит не с любыми объектами, а только с теми, которые наследуются от <tex>Throwable.</tex>
 
В языке <tex>Java</tex> исключения <tex>(Exceptions)</tex> и ошибки <tex>(Errors)</tex> являются объектами. Когда метод вызывает (бросает - throws) исключительную ситуацию, он на самом деле работает с объектом. Но такое происходит не с любыми объектами, а только с теми, которые наследуются от <tex>Throwable.</tex>

Версия 01:28, 18 июня 2013

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

Каждый раз, когда при выполнении программы происходит ошибка, создается объект-исключение, содержащий информацию об ошибке, включая её тип и состояние программы. После создания исключения (?) пытается найти в стеке вызовов метод, который содержит код, обрабатывающий это исключение. Поиск начинается с метода, в котором произошла ошибка, и проходит через стек в обратном порядке вызова методов. Если не было найдено ни одного подходящего обработчика, выполнение программы. завершается.

Таким образом, механизм обработки исключений содержит следующие операции:

  1. Создание объекта-исключения.
  2. Заполнение stack trace'а этого исключения.
  3. Stack unwinding (раскрутка стека) в поисках нужного обработчика.

Введение

В языке [math]Java[/math] исключения [math](Exceptions)[/math] и ошибки [math](Errors)[/math] являются объектами. Когда метод вызывает (бросает - throws) исключительную ситуацию, он на самом деле работает с объектом. Но такое происходит не с любыми объектами, а только с теми, которые наследуются от [math]Throwable.[/math]

Exceptions-throwable.gif

[math]RuntimeException[/math], [math]Error[/math] и их наследников еще называют [math]unchecked[/math] [math]exception[/math], а всех остальных наследников класса [math]Exception -[/math] [math]checked[/math] [math] exception.[/math] [math] Checked[/math] [math] Exception[/math] обязывает пользователя обработать ее (использую конструкцию [math] try-catch [/math].) или же отдать на откуп обрамляющим методам, в таком случае к декларации метода, который бросает проверяемое [math](checked)[/math] исключение, дописывают конструкцию [math]throws[/math], например

public Date parse(String source) throws ParseException { ... }

Так когда же нужно бросать ошибки?

На этот вопрос можно ответить просто: если в методе возможна ситуация, которую метод не в состоянии обработать самостоятельно, он должен “бросать” ошибку. Но ни в коем случае нельзя использовать исключительные ситуации для управления ходом выполнения программы. Чаще всего [math]Exceptions[/math] бросаются при нарушении контракта метода. Нарушение контракта со стороны создателя метода - это, например, что-нибудь на подобии [math]MethodNotImplementedYetException[/math]. Пользователь метода может нарушить контракт, например, таким способом: на вход [math]Integer.parseInt(String)[/math] подать строку с буквами и по заслугам получить [math]NumberFormatException[/math]

А что собственно бросать?

Выбор не то чтобы сильно велик, но и не однозначен: [math]checked,[/math] [math]unchecked[/math] [math](runtime)[/math], [math]unchecked[/math] [math](error).[/math] В подавляющем большинстве случаев [math]Error[/math] вам не понадобится. Это в основном критические ошибки (например, [math]StackOverflowError[/math]), с которыми пусть работает JVM. [math]Checked[/math] [math]Exceptions[/math], как было написано выше, заставляет программиста-пользователя написать код для ее обработки или же описать метод как “вызывающий исключительную ситуацию”. С [math]unchecked[/math] [math] exception[/math] можно поступить по-разному. В случае с такими ошибками, пользователь сам решает, будет он обрабатывать эту ошибку, или же нет (компилятор не заставляет это делать). Можно написать следующее простое правило: если некоторый набор входящих в метод данных может привести к нарушению контракта, и вы считаете, что программисту-пользователю важно разобраться с этим (и что он сможет это сделать), описывайте метод с конструкцией [math]throws[/math], иначе бросайте [math]unchecked[/math] [math]exception.[/math]

Как обрабатывать?

Обрабатывать ошибку лучше там, где она возникла. Если в данном фрагменте кода нет возможности принять решение, что делать с исключением, его нужно бросать дальше, пока не найдется нужный обработчик, либо поток выполнения программы не вылетит совсем.

class intException extends Exception {
  intException(String message){
     super(message);
  }
} 
 class Number {
    int b;
    int division (int a) throws intExceprion{   
        if (a == 0) throw new intException("Division by zero")
           else return this.b / a;
        }
 }
try {
   int c = a.division(b);
   // Безопасное использование результата.
} catch (intException e) {
   // Обработка ошибки
}

Также возможно делать несколько catch

try {
   // Действия
} catch (*Exception e) {
   // Обработка исключения
} catch (*Exception e) {
   // Обработка исключения
} finally {
   // Действия при выходе
}

Блок [math] finally [/math] выполняется в независимости от выполнения [math] catch [/math]