Как устроена иерархия исключений в Java?

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

Ответ

Все исключения и ошибки в Java происходят от общего предка — класса Throwable.

Основные ветви иерархии:

  • Error: Критические ошибки виртуальной машины (например, OutOfMemoryError). Обычно не обрабатываются в прикладном коде.
  • Exception: Базовый класс для исключений приложения. Делится на:
    • Проверяемые (checked) исключения (например, IOException). Требуют обязательной обработки.
    • Непроверяемые (unchecked) исключенияRuntimeException и его наследники (например, NullPointerException). Обработка не обязательна.

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

Пример объявления проверяемого исключения:

// Метод объявляет, что может выбросить IOException
public String readFile(String path) throws IOException {
    return Files.readString(Path.of(path));
}

Пример обработки:

try {
    String content = readFile("config.yaml");
} catch (IOException e) { // Обязательная обработка проверяемого исключения
    // Логируем ошибку и возвращаем значение по умолчанию
    logger.error("Не удалось прочитать файл", e);
    return "default";
}