Когда стоит использовать проверяемые исключения (checked exceptions) при проектировании API в Java?

Ответ

Проверяемые исключения следует использовать осознанно, когда клиент API обязан обработать ошибку и может это сделать разумно.

✅ Подходящие случаи:

  1. Восстановимые ошибки — когда клиент может предпринять альтернативное действие (например, IOException при работе с файлами).
  2. Ошибки бизнес-логики — которые являются частью контракта метода (например, InvalidCredentialsException).

❌ Неподходящие случаи:

  1. Ошибки программирования (например, NullPointerException).
  2. Системные сбои, которые клиент не может исправить (например, ошибки конфигурации).

Пример хорошего использования:

// Клиент ДОЛЖЕН обработать возможность отсутствия файла
public String readConfigFile(String path) throws IOException {
    return Files.readString(Paths.get(path));
}

Пример плохого использования (лучше unchecked):

// Ошибка валидации — обычно это ошибка программиста
public void validate(User user) throws ValidationException {
    if (user == null) {
        throw new ValidationException("User is null");
    }
}
// Лучше:
public void validate(User user) {
    if (user == null) {
        throw new IllegalArgumentException("User must not be null");
    }
}

Основные недостатки проверяемых исключений:

  • Увеличивают шаблонный код (обязательные try-catch или throws).
  • Нарушают принцип открытости/закрытости — изменение сигнатуры метода ломает обратную совместимость.
  • Могут приводить к пустым блокам catch или прокидыванию исключений наверх без реальной обработки.

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

Ответ 18+ 🔞

Да ты посмотри, какая тема подъехала — про эти ваши проверяемые исключения! Ну что, разбираем, блядь, эту дичь.

Смотри, суть-то простая, как три копейки: проверяемые исключения — это когда ты обязываешь того, кто твой метод вызывает, эту ошибку обработать. Не "может быть", а прям обязан, иначе компилятор ему ебальник набьёт. Но это, блядь, не значит, что их нужно везде пихать, как горячие пирожки!

✅ Когда это, блядь, реально нужно:

  1. Ошибки, из которых можно вылезти. Ну, типа, файл не найден (IOException). Клиент может сказать: «Ой, ёпта, ну нет файла — спрошу у пользователя путь другой». Восстановился, красава.
  2. Ошибки по сценарию. Это часть договора, блядь! Типа, InvalidCardException при оплате. Это не сбой программы — это ожидаемый пиздец в бизнес-процессе. Клиент должен на это отреагировать: «Карта не прошла, введите другую, мудила».

❌ Когда это пиздец как не нужно:

  1. Косяки программиста. NullPointerException, ArrayIndexOutOfBoundsException — это тебе не клиента лечить, это тебе самому в жопу ракетой, чтобы код отлаживал. Для этого unchecked исключения, ёбана!
  2. Полный крах системы. Конфиг сломался, база упала — что клиенту с этим делать? Рыдать? Лучше пусть unchecked летит наверх и всё аварийно завершается.

Вот, смотри, годный пример:

// Читаем конфиг. Файла может не быть — это нормальная ситуация, обработай её, будь человеком!
public String readConfigFile(String path) throws IOException {
    return Files.readString(Paths.get(path));
}

А вот пример говна, прости господи:

// Валидация юзера. Если null передали — это кто ошибся? Программист, который метод вызывает!
public void validate(User user) throws ValidationException {
    if (user == null) {
        throw new ValidationException("User is null");
    }
}
// Да иди ты нахуй с такой сигнатурой! Лучше так:
public void validate(User user) {
    if (user == null) {
        throw new IllegalArgumentException("User must not be null, долбоёб!");
    }
}

А теперь, блядь, главный подвох, почему их все так не любят:

  • Код разбухает. Сплошные try-catch и throws в сигнатурах, пиздец просто, читать невозможно.
  • Ломают всё к хуям. Захотел ты новое проверяемое исключение кинуть — готовься, что все, кто твой метод вызывает, тоже должны измениться. Принцип открытости/закрытости? Да пошёл он нахуй в этом месте!
  • Пустые catch-и. И что получается? А получается, что народ, чтобы отстали, просто пишет catch (Exception e) {} и делает вид, что всё окей. Исключение проглотил и живёт дальше, как ни в чём не бывало. Красота, бля!

Так что запомни, как «Отче наш»: по умолчанию — unchecked (RuntimeException). А проверяемые — только для особых случаев, когда ошибка является законной частью работы программы, и с ней надо что-то сделать. Всё остальное — выёбистое усложнение, нахуй не нужное.