Главная » Java » Исключения Java

0

Что следует предпринять, если в программе возникает ошибка? Во многих языках программирования факт возникновения ошибочной ситуации фиксируется каким-нибудь необычным значением (скажем, -1), которое возвращается функцией, виновной в происшедшем. Программисты зачастую всецело пренебрегают средствами проверки корректности работы функций, полагая, что "вот сейчас-то ошибки быть не может". Существует и другая крайность – если пытаться выявить и обработать абсолютно все ситуации, чреватые ошибками, с помощью нагромождения условных выражений, код, доселе простой и понятный, приобретет настолько запутанный и угрожающий вид, что внешняя логика программного текста будет совершенно утрачена. Некая заведомо простая задача, связанная, например, с пересылкой данных из файла в память, может потребовать, скажем, семи строк кода. Снабдив программу исчерпывающими инструкциями обработки ошибок, вы наверняка увеличите объем кода раз, этак, в пять или шесть. Разумеется, недопустимо, чтобы основные функции программы, ответственные за решение задачи как таковой, терялись в дебрях вспомогательных конструкций подобно иголке в стоге сена.

Справиться с проблемой обработки ошибочных ситуаций помогают средства поддержки объявляемых исключений. Применяя аппарат объявляемых исключений, вы как автор программы вынуждены задумываться о том, что делать с ошибками, которые, возможно, возникнут в том или ином месте кода. Если исключение, объявленное вами, никак не обрабатывается, об этом вы будете поставлены в известность уже на этапе компиляции, а не в момент выполнения Программы, когда не замеченные вовремя проблемы, наслаиваясь одна на другую, затрудняют поиск первичного источника ошибки.

Метод, обнаруживший неожиданную ошибочную ситуацию, генерирует, или, как принято выражаться, выбрасывает (throw), исключение. Исключения могут быть обработаны, или, попросту говоря, отловлены (catch), кодом, который, Возможно, расположен в стеке вызовов несколько ранее, – подобный код способен справиться с ситуацией таким образом, как это предусмотрено программистом, и позволить приложению продолжить работу. Исключения, не подвергшиеся обработке, приводят к завершению потока вычислений, но прежде Соответствующему объекту класса ThreadGroup все-таки предоставляется последний шанс каким-то наиболее приемлемым в конкретной ситуации способом "поладить" с исключением – вполне вероятно, не предложив ничего другого, кроме печальной констатации происшедшего. Классы Thread и ThreadGroup, имеющие непосредственное отношение к потокам вычислений, подробно рассмотрены в главе 10.

Исключение – это объект определенного типа, обладающий собственными полями и методами. Подход, связанный с реализацией исключений в Виде объектов, весьма плодотворен, поскольку объект исключения может содержать данные, методы либо то и другое одновременно, и это облегчает задачи идентификации конкретной ошибки и устранения ее последствий. Классы исключений обычно наследуются от базового класса Exception, в котором предусмотрено строковое поле для хранения текстовой информации об ошибке и способах ее исправления. Exception, в свою очередь, унаследован от класса Throwablе, базового по отношению ко всем возможным классам исключений.

Обработка исключений реализуется в рамках следующей общей конструкции: try … catch … finally. Программа пытается (try) выполнить определенные операции; если в результате работы возникает или Принудительно выбрасывается (throw) исключение, оно отлавливается (catch) и обрабатывается; и, наконец (finallу), программа получает возможность осуществить дополнительные действия по приведению своего внутреннего состояния в порядок, необходимые либо в случае нормального протекания процесса, либо после обработки исключительной ситуации, независимо от того, что произошло на самом деле.

Ниже приведен пример метода getDataSet, который возвращает набор данных, считанных из файла. Если файл не может быть найден или происходит любая другая ошибка ввода-вывода, метод генерирует соответствующее исключение. Прежде всего мы определяем новый тип исключения BadDataSetExcepti оп, отвечающий природе вероятных ошибок. Затем в теле некоторого класса MyUtilities объявляем метод getDataSet и с помощью предложения throws этого объявления оговариваем, что метод способен выбрасывать исключение определенного нами типа.

class BadDataSetException extends Exception {}

 

class Myutilities {

                public double[] getDataSet(String setName) throws

                                BadDataSetException

                               {

                                               Ыtring file = setName + ".dset";

FilelnputStream in = null;

                                               try {

                                               in = new FilelnputStream(file);

                                               return readDataSet(in);

                                               } catch (IoException е) {

                                                  throw new BadDataSetException();

} finally {

                                                                              try {

                                                                                              if (in != null) in.closeO;

                                                                              } catch (IoException е) {

          ;   // Можно не обращать внимания

 // данные уже получены!

}

}

}

// … объявление метода readDataSet …

}

 

Сначала, используя содержимое параметра setName, мы формируем имя файла, а затем в блоке try пытаемся открыть этот файл и прочесть данные из него с помощью метода readDataSet. При благополучном исходе readDataSet возвращает массив значений типа doub1е, который, в свою очередь, служит результатом работы метода getDataSet. Если операции открытия или Чтения файла приводят к Возникновению Исключительной ситуации, управление Переедается блоку catch. В последнем создается и выбрасывается объект Исключения BadDataSetException, подменяющий собою объект Исключения стандартного типа IOException. Некоторый код, содержащий вызов метода getDataSet, позже Сможет отловить объект Исключения созданного нами типа и отреагировать на обстоятельства должным образом. Далее в любой ситуации – либо После успешного открытия и чтения файла, либо вслед за инструкциями блока catch – Выполняется предложение finally, Позволяющее произвести необходимые завершающие операции (в нашем примере – закрыть файл, если Предварительно тот был успешно открыт). Если иключение генерируется при попытке закрытия файла, оно отлавливается, но игнорируется – в тексте вы видите отдельный символ точки с запятой, обозначающий пустое выражение. Вообще говоря, пренебрегать Исключениями, возникающими в процессе работы программы, не стоит, но в данном случае предполагается, что ошибка проявляется уже после успешного Извлечения данных из файла, и поэтому можно считать, что оговоренный контракт удовлетворен и миссия, возложенная на метод, Выполнена. Если ошибка повторится, она будет зафиксирована при следующей попытке работы с файлом, и тогда, вероятно, программа сможет предпринять более эффективные меры для разрешения проблемы.

Еще раз подчеркнем, что блок finally предоставляет возможность задать все необходимые инструкции восстановительного характера, Которые должны выполняться в любой ситуации. Вообще говоря, ничто не запрещает применять и такую конструкцию try … finallу, в которой Вовсе отсутствует блок catch. Это позволит гарантировать, что код finallу будет Выполнен всегда, даже в том Случае, когда выбрасывается Исключение, для которого соответствующее предложение catch не предусмотрено.

Если метод способен генерировать Исключения, типы этих исключений должны быть перечислены в секции throws объявления метода (как в Примере, приведенном Выше). Конкретному методу Позволено выбрасывать только те Исключения, которые указаны в его объявлении, – вот почему их называют объявляемыми. В теле метода исключения могут выбрасываться либо Принудительно, посредством Выражения throw, либо косвенно, при вызове другого метода, который способен иx генерировать. Исключения классов RuntimeException, Еrror и производных от них типов относятся к категории необьявляемых исключений и могут генерироваться при любых обстоятельствах без предварительного уведомления.

Объявляемые исключения служат для описания ситуаций, которые, несмотря на их непредсказуемый и "исключительный" характер, вполне вероятны, и посколыку они могут произойти, С ними приходится считаться – как, например, исключением типа IOException, которое возникает, в частности, при выполнении файловых операций. Список генерируемых исключений, заданный в объявлении метода, позволяет компилятору проверить код и убедиться, действительно ли метод выбрасывает только те исключения, которые им объявлены. Подобная проверка способна предотвратить ошибки в тех ситуациях, когда, например, рассматриваемый метод должен обрабатывать исключения, генерируемые другим методом, но не выполняет этого требования. С другой стороны, если наш метод вызывается другим методом, последний должен быть "уверен" в том, что первый не выбросит какого-либо исключения, которое предварительно не объявлено.

Необъявляемые исключения, возникающие в процессе работы программы, вообще говоря, служат признаком ошибочности ее логики, и вызвавшие их проблемы обычно не могут быть преодолены на этапе выполнения приложения. Например, исключение типа IndexoutOfBoundsException, генерируемое при попытке доступа к элементу массива, свидетельствует о том, что программа вычисляет значение индекса элемента неверно либо не проверяет корректность выражения, употребляемого в качестве индекса. Ошибки такого рода должны исправляться в исходном коде. Хотя, разумеется, любое выражение программы чревато ошибками, будет совершенно неразумно полагать, что мы обязаны предварительно объявлять и пытаться "поймать" буквально все исключения, – этой цели и служат необъявляемые исключения.

Упражнение 1.15. Добавьте в состав класса BadDataSetException поля для хранения имени файла и объекта исключения IOException, который фиксирует проблему, чтобы код, вызывающий метод getDataSet, получил в свое распоряжение более полную информацию о природе ошибки.

Источник: Арнолд, Кен, Гослинг, Джеймс, Холмс, Дэвид. Язык программирования Java. 3-е изд .. : Пер. с англ. – М. : Издательский дом «Вильяме», 2001. – 624 с. : ил. – Парал. тит. англ.

По теме:

  • Комментарии