Лекция 04. Исключения ####################################################################################### Исключения =========================================================== Обработка исключений `````````````````````````````````````````````````````````` Классификация типов ошибок: * Build-time errors - Синтаксические - Семантические - Логические * Run-time errors (исключения) Понятие исключения `````````````````````````````````````````````````````````` **Исключение в Java** — это объект некоторого класса, который описывает исключительное состояние, возникшее в каком-либо участке программного кода. При возникновении исключения исполняющая система Java создает объект класса, связанного с данным исключением. Этот объект хранит информацию о возникшей исключительной ситуации (точка возникновения, описание и т.п.) Возможна как автоматическая так и программная генерация исключений. Иерархия исключений `````````````````````````````````````````````````````````` В языке Java исключения образуют иерархию классов: .. image:: _static/04/except.png Среди исключений выделяют: #. **Errors** - ошибки, связанные с работой виртуальной машины. Программой не обрабатываются (исчерпание памяти и т.д.) #. **Runtime Exceptions** - **необрабатываемые** исключения, унаследованные от класса **RuntimeException**. Могут обрабатываться в программе, а могут и нет (например, **NullPointException**). #. **Exceptions**, не унаследованные от **RuntimeException** и считающиеся **обрабатываемыми**. Требуют обязательной обработки. Формат обработчика `````````````````````````````````````````````````````````` .. code-block:: java try { // блок кода } catch (ExceptionType1 еxOb1) { // обработчик исключений типа ExceptionType1 } catch (ExceptionType2 еxOb2) { // обработчик исключений типа ExceptionType2 } finally { //код, который выполняется перед выходом из блока try } Пример `````````````````````````````````````````````````````````` .. code-block:: java try { read_from_file ("data.txt"); calculate(); } catch ( FileNotFoundException fe ) { System.out.println("Файл data.txt не найден"); } catch ( ArithmeticException aex ) { System.out.println("Деление на ноль"); } try-catch блок `````````````````````````````````````````````````````````` * управление никогда не возвращается из блока catch обратно в блок try, после выполнения catch-блока управление передается строке, следующей сразу после try-catch-блока; * область видимости catch-блока ограничена ближайшим предшествующим утверждением try, т.е. catch-блок не может захватывать исключение, выброшенное «не своим» try-блоком; * операторы, контролируемые утверждением try, должны быть окружены фигурными скобками даже если это одиночная инструкция. * блоки try могут быть вложенными Catch-блоки просматриваются в порядке их появления в программе, при этом обработчик catch для суперкласса перехватывает исключения как для своего класса так и для всех его подклассов. Следовательно, в последовательности catch-блоков подклассы исключений должны следовать перед любым из суперклассов. Программная генерация `````````````````````````````````````````````````````````` Программная генерация исключения: .. code-block:: java throw new (); throw new ("..."); Оператор throw `````````````````````````````````````````````````````````` .. code-block:: java public 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); } } Оператор Throws `````````````````````````````````````````````````````````` Исключения, которые порождены от **Exception**, но не от **RuntimeException**, могут быть сгенерированы только явно операцией **throw**. При этом если метод может выбрасывать одно из таких исключений, то должно выполняться одно из двух условий: * либо для такого исключения должен быть catch-обработчик, * либо в заголовке такого метода должна стоять конструкция: .. code-block:: java throws ... public String readLine() throws IOException (т.н. Catch or Specify Requirement) Вызов метода, в описании которого стоит **"throws ... "**, тоже должен находиться либо внутри **try-catch-блока**, либо внутри метода с конструкцией **" throws ... "** в его заголовке и т.д. вплоть до метода main(). Таким образом, где-то в программе любое возможное исключение, попадающее в категорию **Catch** or **Specify Requirement** обязано быть перехвачено и обработано. Подклассы Exception `````````````````````````````````````````````````````````` .. code-block:: java class MyException extends Exception { private int detail; MyException(int a) { detail = a; } public String toString() { return "MyException[" + detail + "]"; } } Если надо создать исключение необязательное к перехвату – его надо унаследовать от **RuntimeException**. Вопросы для самоконтроля =============================================