Зачем в Java существует иерархия исключений (Exception Hierarchy)?

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

Ответ

Иерархия исключений в Java обеспечивает структурированную, гибкую и типобезопасную модель обработки ошибок.

Структура иерархии:

Throwable
├── Error (непроверяемые, фатальные: OutOfMemoryError, StackOverflowError)
└── Exception
    ├── RuntimeException (непроверяемые: NullPointerException, IllegalArgumentException)
    └── Проверяемые исключения (checked: IOException, SQLException)

Преимущества иерархии:

  1. Группировка и полиморфизм: Можно обрабатывать исключения на нужном уровне детализации.

    try {
        // Код, который может выбросить разные IOException
    } catch (FileNotFoundException e) {
        // Обработка конкретной ситуации
    } catch (IOException e) {
        // Общая обработка всех остальных ошибок ввода-вывода
    }
  2. Разделение ответственности:

    • Проверяемые (Checked) исключения — для ошибок, от которых программа может оправиться (файл не найден, сетевой сбой). Компилятор заставляет их либо обработать (catch), либо объявить в сигнатуре метода (throws).
    • Непроверяемые (Unchecked: RuntimeException) — для ошибок программирования (обращение к null, неверный аргумент). Обычно указывают на баг в коде.
    • Error — для критических системных сбоев (JVM), которые обычно не обрабатываются.
  3. Возможность создания собственных исключений: Наследование от Exception или RuntimeException позволяет создавать доменно-специфичные типы ошибок.

    class InsufficientFundsException extends RuntimeException {
        public InsufficientFundsException(String message) {
            super(message);
        }
    }
    // Использование:
    throw new InsufficientFundsException("Balance is too low");

Эта система делает код более надежным и понятным, явно разделяя ожидаемые и неожиданные условия ошибок.