Спецификация Java 11: 11.2.3. Проверка исключений

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

Это ошибка времени компиляции, если тело лямбда может вызвать некоторый класс исключения E, когда E является проверенным классом исключения, а E не является подклассом некоторого класса, объявленного в предложении throws типа функции, на который нацелено лямбда-выражение.

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

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

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

Это ошибка времени компиляции, если предложение catch может перехватить проверенный класс исключения E1, и это не тот случай, когда блок try, соответствующий предложению catch, может генерировать проверенный класс исключения, который является подклассом или суперклассом E1, если только E1 не является Exception или суперкласс Exception.

Это ошибка времени компиляции, если предложение catch может перехватить класс исключения E1, а предшествующее предложение catch непосредственно включающего оператора try может перехватить E1 или суперкласс E1.

Компилятору Java рекомендуется выдавать предупреждение, если предложение catch может перехватывать проверенный класс исключения E1, а блок try, соответствующий предложению catch, может генерировать проверенный класс исключения E2, где E2 <: E1, и предшествующее предложение catch немедленно включающего оператора try может перехватить проверенный класс исключения E3, где E2 <: E3 <: E1.

Пример отлавливания проверенных исключений

import java.io.*;

class StaticallyThrownExceptionsIncludeSubtypes {
    public static void main(String[] args) {
        try {
            throw new FileNotFoundException();
        } catch (IOException ioe) {
            // "catch IOException" отлавливает IOException 
            // и любой подтип.
        }

        try {
            throw new FileNotFoundException();
              // Заявление "can throw" ("может вызвать") 
              // исключение FileNotFoundException.
              // Это не тот случай, когда оператор "может вызвать"
              // подтип или супертип FileNotFoundException.
        } catch (FileNotFoundException fnfe) {
            // ... Обработка исключения ...
        } catch (IOException ioe) {
            // Допустимо, но компиляторам рекомендуется указывать
            // предупреждения начиная с Java SE 7, 
            // потому что все подтипы исключения IOException, 
            // которые блок try "может выбросить",
            // уже были пойманы предыдущим предложением catch.
        }

        try {
            m();
            // В объявлении m написано "throws IOException", поэтому
            // m "может выбросить" ("can throw") IOException. 
            // Это не значит что m "может выбросить" 
            // подтип или супертип исключения IOException 
            // (например, Exception).
        } catch (FileNotFoundException fnfe) {
            // Допустимо, потому что динамический тип исключения
            // может быть FileNotFoundException.
        } catch (IOException ioe) {
            // Допустимо, потому что динамический тип исключения
            // может быть другой подтип IOException.
        } catch (Throwable t) {
            // Всегда можно поймать Throwable.
        }
    }

    static void m() throws IOException {
        throw new FileNotFoundException();
    }
}

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

try { ... }
catch (Foo f) { ... }
catch (Bar | SubclassOfFoo e) { ... }


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки