Как компилятор Java реагирует на непроверенные проверяемые исключения (checked exceptions)?

«Как компилятор Java реагирует на непроверенные проверяемые исключения (checked exceptions)?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Компилятор Java выполняет статическую проверку (compile-time checking) для проверяемых исключений (классы, наследующие Exception, но не RuntimeException).

Правило: Если метод может сгенерировать проверяемое исключение, он должен либо:

  1. Объявить его в своей сигнатуре с помощью throws.
  2. Обработать его внутри с помощью блока try-catch.

Пример 1: Объявление исключения

public void readFile(String path) throws IOException {
    // Код, который может вызвать FileNotFoundException (наследник IOException)
    Files.readAllLines(Paths.get(path));
}

Пример 2: Обработка исключения

public void readFile(String path) {
    try {
        Files.readAllLines(Paths.get(path));
    } catch (IOException e) { // IOException перехвачено и обработано
        System.err.println("Файл не найден: " + e.getMessage());
    }
}

Если правило нарушено, компилятор выдаст ошибку: unreported exception <ExceptionClass>; must be caught or declared to be thrown

Важно: Это правило не применяется к непроверяемым исключениям (RuntimeException, например, NullPointerException) и ошибкам (Error, например, OutOfMemoryError).