Почему в Java не следует бездумно обрабатывать unchecked исключения (RuntimeException)?

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

Ответ

Unchecked-исключения (RuntimeException и его наследники) обычно указывают на ошибки программирования или неверное состояние программы. Их глобальная обработка часто маскирует коренную проблему, которую нужно исправить в коде.

Почему это плохая практика:

try {
    process(user.getProfile().getAddress().getCity()); // Цепочка вызовов
} catch (NullPointerException e) {
    log.error("Объект не найден", e); // Плохо: скрыли источник проблемы
    return null;
}

Такой код скрывает, какой именно объект был null.

Лучшие практики:

  1. Предотвращайте, а не обрабатывайте: Проверяйте предварительные условия.
    // Вместо catch(NullPointerException)
    if (user != null && user.getProfile() != null && user.getProfile().getAddress() != null) {
        process(user.getProfile().getAddress().getCity());
    }
    // Или используйте Optional
    Optional.ofNullable(user)
            .map(User::getProfile)
            .map(Profile::getAddress)
            .map(Address::getCity)
            .ifPresent(this::process);
  2. Валидируйте входные данные: Используйте IllegalArgumentException для сигнализации о неверных аргументах.
  3. Обрабатывайте на верхнем уровне: Ловите RuntimeException только на границах приложения (в контроллерах, сервлетах) для логирования и возврата пользователю понятной ошибки, не прерывая работу всего приложения.

Исключение: Обработка конкретных unchecked исключений (например, NumberFormatException при парсинге ввода пользователя) допустима, если это часть бизнес-логики.