Вопрос 2 · Раздел 7

Что такое checked exception и когда его использовать?

Используйте checked exception если:

Версии по языкам: English Russian Ukrainian

Junior Level

Определение

Checked exception (проверяемое исключение) — это тип исключения, который компилятор Java обязывает обработать.

Зачем: Java-дизайнеры хотели заставить разработчика явно решить, как реагировать на предсказуемые внешние сбои – файл может отсутствовать, сеть может пропасть. Без checked exceptions эти ситуации легко пропустить. Если метод может выбросить checked exception, вы должны:

  1. Обернуть вызов в try-catch
  2. Или добавить throws в сигнатуру метода

Примеры

// Компилятор заставит обработать IOException
public String readFile() throws IOException {
    return Files.readString(Paths.get("data.txt"));
}

// Обязаны обработать
public void safeRead() {
    try {
        Files.readString(Paths.get("data.txt"));
    } catch (IOException e) {
        System.err.println("Failed to read: " + e.getMessage());
    }
}

Когда использовать

Используйте checked exception если:

  • Сбой ожидаем — файл может отсутствовать, сеть может пропасть
  • Сбой восстановим — можно повторить попытку, попробовать другой путь
  • Это критично — нельзя просто “забыть” об этой ситуации

Распространённые checked исключения

  • IOException — проблемы ввода-вывода
  • SQLException — ошибки базы данных
  • ClassNotFoundException — класс не найден
  • InterruptedException — поток прерван

Middle Level

Что выбрать: throws или try-catch?

  • throws – когда метод не может принять решение об обработке. Пусть вызывающий решает.
  • try-catch – когда можете обработать на месте: залогировать, вернуть дефолтное значение, повторить запрос.

Механизм компиляции

Компилятор javac проверяет граф вызовов. Если где-то в цепочке вызывается метод с checked исключением и оно не обработано, компиляция прервётся.

Exception Translation

В крупных проектах с многослойной архитектурой проброс checked исключений нарушает инкапсуляцию слоёв. В небольших проектах допустимо пробрасывать их наверх.

public Order createOrder(Order order) {
    try {
        return orderRepository.save(order);
    } catch (SQLException e) {
        throw new OrderStorageException("Failed to save order", e);
    }
}

OrderStorageException — это runtime исключение. Бизнес-логика не зависит от JDBC.

Три условия использования checked exceptions

  1. Сбой ожидаем — не баг в коде, а внешнее обстоятельство
  2. Сбой восстановим — вызывающий код может что-то предпринять
  3. Критично для бизнеса — нельзя проигнорировать

Lambda и checked exceptions

Функциональные интерфейсы не поддерживают checked исключения:

// Не скомпилируется!
list.stream().map(path -> Files.readString(path))
// Почему: интерфейс Function<T,R> не объявляет throws в сигнатуре apply().
// Поэтому лямбда не может пробросить checked exception -- компилятор не пропустит.

// Решение — обёртка
list.stream().map(path -> {
    try {
        return Files.readString(path);
    } catch (IOException e) {
        throw new UncheckedIOException(e);
    }
})

Senior Level

Under the Hood: атрибут Exceptions

В .class файле информация о throws сохраняется в атрибуте метода Exceptions. JVM не использует его для контроля в рантайме — только для верификатора компилятора.

Binary Compatibility

Добавление checked исключения в метод существующей библиотеки ломает бинарную совместимость. Все клиенты перестанут компилироваться.

Удаление исключения — бинарно совместимо, но оставляет лишний код у клиентов.

Overriding и LSP

Принцип подстановки Лисков диктует правила:

  • Метод-наследник может не выбрасывать исключения родителя
  • Может выбрасывать подтипы исключений родителя
  • НЕ может выбрасывать новые checked исключения

Производительность

Checked исключение — это всё ещё Throwable с дорогим fillInStackTrace(). Для частых “ожидаемых” ситуаций лучше возвращать Optional<T> или Result-объекты.

Edge Cases

  • InterruptedException — “хорошее” checked исключение. При перехвате восстанавливайте статус: Thread.currentThread().interrupt()
  • Generic Throws — Java позволяет public <E extends Exception> void doWork() throws E
  • throws Exception — никогда не пишите так в публичном API

Мониторинг

Не бросайте Exception или Throwable. Создавайте свои типы для чёткого разделения ошибок в Micrometer/Prometheus.


🎯 Шпаргалка для интервью

Обязательно знать:

  • Checked exception — компилятор обязывает обработать (try-catch или throws)
  • Использовать, если сбой ожидаем, восстановим и критичен для бизнеса
  • Распространённые: IOException, SQLException, ClassNotFoundException, InterruptedException
  • throws — когда метод не может решить, как обработать; try-catch — когда можете
  • Exception Translation — оборачивание checked в доменное unchecked для слоёв архитектуры
  • Lambda не поддерживает checked исключения — нужна обёртка в UncheckedIOException
  • Добавление checked исключения ломает бинарную совместимость библиотеки
  • При overriding метод-наследник НЕ может добавлять новые checked исключения (LSP)

Частые уточняющие вопросы:

  • Почему checked исключения не работают с лямбдами? — Функциональные интерфейсы (Function, Predicate) не объявляют throws в сигнатуре
  • Что будет при добавлении checked исключения в публичный API библиотеки? — Все клиенты перестанут компилироваться — ломает бинарную совместимость
  • Как правильно обработать InterruptedException? — Перехватить и восстановить статус: Thread.currentThread().interrupt()
  • Когда checked exception лучше unchecked? — Когда вызывающий может что-то предпринять (повторить, выбрать альтернативный путь)

Красные флаги (НЕ говорить):

  • “Я пишу throws Exception везде, чтобы не думать” — это ломает контракт метода
  • “Checked exceptions — это проблема JVM, а не приложения” — нет, это ошибки приложения
  • “Я перехватываю все checked исключения и ничего не делаю” — молчаливое проглатывание ошибок

Связанные темы:

  • [[В чём разница между checked и unchecked exceptions]]
  • [[Что такое unchecked exception (Runtime Exception)]]
  • [[Какие исключения нужно обрабатывать обязательно]]
  • [[Что находится в вершине иерархии исключений]]
  • [[Что такое Throwable]]