На этом шаге мы начнем говорить про обработку ошибок
Допустим, в ходе выполнения программы, обнаруживается ошибка. Она может быть вызвана неверной информацией в файле, ненадежным сетевым соединением или выходом за допустимые границы массива. Вполне естественно, пользователи надеются, что программа самостоятельно справится с возникшими затруднениями. Если из-за ошибки какая-нибудь операция не может быть завершена благополучно, программа должна сделать одно из двух:
Добиться этого не так-то просто: фрагмент кода, в котором обнаруживается ошибка, обычно находится очень далеко от кода, который может восстановить данные и сохранить результаты, полученные пользователем. Поэтому основное назначение механизма обработки исключений - передать данные обработчику исключений из того места, где возник сбой. Предусматривая обработку исключений в программе, следует предвидеть возможные ошибки и связанные с ними осложнения.
Обычно метод сообщает об ошибке, возвращая специальный код, который анализируется вызывающим методом. Например, методы, вводящие данные из файлов, обычно возвращают значение -1 по достижении конца файла. Такой способ обработки ошибок часто оказывается эффективным. В других случаях в качестве признака ошибки возвращается пустое значение null.
К сожалению, возможность возвращать код ошибки имеется далеко не всегда. Иногда правильные данные не удается отличить от признаков ошибок. Так, метод, возвращающий целое значение, вряд ли возвратит значение -1, обнаружив ошибку, поскольку оно может быть получено в результате вычислений.
В Java имеется возможность предусмотреть в каждом методе альтернативный выход, которым следует воспользоваться, если нормальное выполнение задания нельзя довести до конца. В этом случае метол не станет возвращать значение, а сгенерирует объект, инкапсулирующий сведения о возникшей ошибке. Следует, однако, иметь в виду, что выход из метода происходит незамедлительно, и он не возвращает своего нормального значения. Более того, возобновить выполнение кода, вызвавшего данный метод, невозможно. Вместо этого начинается поиск обработчика исключений, который может справиться с возникшей ошибочной ситуацией.
Исключения имеют свой собственный синтаксис и являются частью особой иерархии наследования.
В Java объект исключения всегда является экземпляром класса, производного класса Throwable. Если это требуется, то можно создавать свои классы исключений. На рисунке 1 показана упрощенная версия иерархии наследования исключений в Java.
Рис. 1. Иерархия наследования исключений в Java
Обратим внимание на то, что иерархия наследования исключений разделена на две ветви: Error и Exception. Иерархия класса Error описывает внутренние ошибки и ситуации, возникающие в связи с нехваткой ресурсов в исполняющей системе Java. Ни один объект этого класса нельзя сгенерировать самостоятельно. При возникновении внутренней ошибки в такой системе возможности разработчика прикладной программы крайне ограничены. Можно лишь уведомить пользователя и попытаться аккуратно прервать выполнение программы, хотя такие ситуации достаточно редки.
При программировании на Java основное внимание следует уделять иерархии класса Exception. Эта иерархия также разделена на две ветви: исключения, производные от класса RuntimeException и остальные. Исключения типа RuntimeException возникают вследствие ошибок программирования. Все другие виды исключений являются следствием непредвиденного стечения обстоятельств, например, ошибок ввода-вывода, возникающих при выполнении вполне корректных программ.
Исключения, производные от класса RuntimeExcpetion, связаны со следующими программными ошибками:
Остальные исключения возникают в следующих случаях:
Исключения типа RuntimeException практически всегда возникают по вине программиста. Например, исключение типа ArrayIndexOutBoundsException никогда не возникнет, если перед тем, как воспользоваться переменной, проверить не содержит ли она пустое значение null.
Предположим, что мы хотим считать данные с файла, предварительно проверив наличие требуемого файла. К сожалению, проверка не дает гарантии не возникновении исключительной ситуации, так как файл может быть удален сразу же после проверки.
В спецификации языка Java любое исключение, производное от класса Error или RuntimeError, называется не проверяемым (unchecked). Все остальные исключения называются проверяемыми (checked). Для всех проверяемых исключений компилятор проверяет наличие соответствующих обработчиков.
На следующем шаге мы поговорим про проброс проверяемых исключений