Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие Java .pdf
Скачиваний:
118
Добавлен:
16.03.2015
Размер:
1.32 Mб
Скачать

В состав класса NoSuchAttributeException, производного от Exception, добавлены конструктор, принимающий в качестве параметра строку наименования атрибута, и публичное поле, предназначенное для ее хранения. В теле конструктора вызывается конструктор базового класса, которому передается строка описания ошибки. С точки зрения кода, выполняющего обработку ошибок, рассмотренный тип исключений достаточно полезен, так как он содержит и внятное описание ошибки, и наименование атрибута, отсутствие которого привело к ее возникновению.

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

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

3.2 Инструкция throw

Исключения могут быть выброшены методами и операторами, которые вы используете в своей программе. Кроме того, вы можете выбросить исключение в своём коде, для этого используется инструкция throw, имеющая следующий формат:

throw <Выражение>;

122

где <Выражение> обязано возвращать ссылку на объект типа Throwable. В примере 58 показана генерация описанного ранее исключения NoSuchAttributeException.

Пример 58. Явное выбрасывание исключения

public void replaceValue(String name, Object newValue) throws NoSuchAttributeException {

Attr attr = find(name); if (attr == null)

throw new NoSuchAttributeException(name); attr.setValue(newValue);

}

В теле метода replaceValue() сначала вызывается метод, выполняющий поиск атрибута по заданному имени. Если поиска не удался, объект исключения типа NoSuchAttributeException вначале создается, с передачей его конструктору строки имени атрибута, а затем выбрасывается. Исключение – это объект, поэтому,

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

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

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

123

составляющие правостороннего операнда больше не анализируются. Аналогично, если появление исключения спровоцировал левый аргумент в любой части выражения, все аргументы справа от него игнорируются. Следующим будет выполнен либо «завершающий» блок finally, либо блок catch, обрабатывающий исключение.

Результатом работы инструкции throw служит синхронное (synchronous) исключение – то же самое происходит, например, при целочисленном делении на ноль: исключение возникает как непосредственный итог выполнения определенной инструкции, причем неважно, выбрасывается ли оно явно, командой throw, либо косвенно, исполняющей системой, обнаружившей, например,

факт деления на ноль. Асинхронное (asynchronous) исключение

также возникает при выполнении инструкции, но причина возникновения исключения находится не в этой инструкции.

Асинхронные исключения проявляются в двух ситуациях. Первая связана с внутренними ошибками виртуальной машины Java – такие исключения считаются асинхронными, поскольку их появление провоцируется кодом виртуальной машины, а не инструкциями приложения. Понятно, что с подобными ошибками автору прикладной программы в подавляющем большинстве случаев справиться не удастся. Примером такой ситуации может служить нехватка памяти при создании объектов: место выбрасывания исключения OutOfMemoryException будет определяться, по сути, не выполняемой инструкцией создания объекта, а количеством памяти JVM, указываемом при запуске виртуальноймашины.

Ко второй группе причин возникновения асинхронных исключений относится использование устаревших и не рекомендованных для применения методов (например, Thread.stop), а также подобных им разрешённых методов (например, stopThread) из состава JavaTM

Virtual Machine Debug Interface (JVMDI) – native-интерфейса вирту-

альной машины, позволяющего проверять состояние работающих

124

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

3.3Предложения throws

Впримере 58 в объявлении метода replaceValue() ясно указано, какие объявленные исключения он способен генерировать. Язык требует предоставления подобной информации, поскольку сведения об исключениях, которые могут быть выброшены методом, важны в такой же степени, как и данные о типе возвращаемого им значения. Поэтому логично в объявлении метода указывать не только тип возвращаемого значения, но и список возможных исключений.

Объявляемые методом исключения указываются с помощью предложения throws в виде списка наименований типов исключений, разделяемых символом запятой. В списке обязаны присутствовать те объявляемые исключения, которые генерируются (тем или иным способом) в методе, но не обрабатываются в его теле.

Метод вправе выбрасывать исключения типов, производных от тех, которые объявлены в предложении throws: язык позволяет полиморфным образом использовать объекты производных типов

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

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

125

удобства использования и возможностей развития кода предложение throws должно быть настолько полным и точным в деталях, насколько это приемлемо в конкретной ситуации.

Часть контракта метода, определяемая предложением throws, строго проверяется на этапе компиляции: метод вправе выбрасывать объявляемые исключения только тех типов, которые явно названы. Выбрасывание объявляемых исключений других типов – как непосредственное, с помощью инструкции throw, так и косвенное, вследствие обращения к другим методам, запрещается. Если в объявлении метода вообще отсутствует предложение throws, это не значит, что не могут быть выброшены какие-либо исключения – речь идёт только о невозможности генерирования объявляемых исключений.

Поскольку типы объявляемых исключений должны быть указаны в предложении throws, отсюда следует, что фрагменты кода, не находящиеся в методах с предложением throws, не вправе выбрасывать объявляемые исключения ни явно, ни косвенно (либо обязаны их явно отлавливать и обрабатывать). Такими фрагментами кода являются блоки инициализации классов (в них можно явно отловить исключение) и инициализаторы полей (никак не могут отлавливать исключения). Однако в действительности блоки инициализации и инициализаторы полей могут выбрасывать объявляемые исключения, но только если блоки и поля не являются статическими, а типы исключений объявлены во всех конструкторах класса. Статические инициализаторы, действительно, никак не могут выбрасывать объявляемые исключения.

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

отловить исключения и обработать их;

126

Соседние файлы в предмете Программирование на Java