ПрограммированиеBackend разработчик

Чем отличаются checked и unchecked exceptions в Java, как правильно проектировать обработку ошибок и каких ошибок следует избегать при их использовании?

Проходите собеседования с ИИ помощником Hintsage

Ответ

В Java исключения делятся на checked (проверяемые) и unchecked (непроверяемые).

  • Checked exceptions — наследуются от Exception, но не от RuntimeException. Компилятор требует явно обработать их с помощью try-catch либо объявить в throws.
  • Unchecked exceptions — наследуются от RuntimeException. Компилятор не требует их обязательной обработки.
public void readFile(String file) throws IOException { /* ... */ } // checked public void divide(int a, int b) { int res = a/b; } // unchecked (ArithmeticException)

Главная тонкость — checked exceptions используются для ожидаемых, восстанавливаемых ситуаций (например, ошибки ввода-вывода), тогда как unchecked — для ошибок программной логики или критических ситуаций, от которых нельзя восстановиться (например, NullPointerException).

Вопрос с подвохом

Вопрос: Нужно ли обработать или объявить в throws unchecked exception, если ваш метод может их выбросить?

Ответ: Нет. Проверять или объявлять невосстановимые (unchecked) исключения компилятор не требует. Их обработка на ваше усмотрение; можно использовать try-catch, но чаще — дать "упасть" вплоть до глобального обработчика.

public void foo() { throw new IllegalArgumentException(); } // Не требует обработки или объявления

Примеры реальных ошибок из-за незнания тонкостей темы


История

В проекте банковского API при обработке ошибок ввода-вывода бросали RuntimeException вместо checked. В результате клиенты не были вынуждены их обрабатывать, что приводило к некорректной работе при потере соединения с сервером, и приложение "падало" без информирования пользователя.


История

Разработчик объявил лишнее количество throws Exception в сигнатуре методов (например, базы данных), из-за чего все используемые методы выше были вынуждены либо try-catch, либо тоже throws. Это замусорило код, ухудшило читабельность и затрудняло рефакторинг.


История

В одном из микросервисов ловили все исключения общим catch (Exception e). Это перехватывало и unchecked exception'ы (например, NullPointerException), что приводило к "тихому" игнорированию критических ошибок — сервис работал с некорректными данными.