Когда в Java следует выбрасывать проверяемое (checked), а когда непроверяемое (unchecked) исключение?

Ответ

Выбор зависит от природы ошибки и ответственности за её обработку.

Проверяемые исключения (checked, например, IOException) следует использовать, когда:

  • Ошибка является ожидаемой частью работы метода (например, файл не найден, сетевое соединение разорвано).
  • Клиентский код может и должен осмысленно обработать эту ситуацию и восстановить работу.
  • Компилятор принуждает обработать исключение через try-catch или объявить в throws.
// Проверяемое исключение — клиент должен решить, что делать, если файла нет
public String readConfigFile(String path) throws IOException {
    return Files.readString(Paths.get(path));
}

Непроверяемые исключения (unchecked, наследники RuntimeException) следует использовать, когда:

  • Ошибка указывает на ошибку программиста или некорректное состояние программы (например, передача null в метод, требующий не-null, деление на ноль).
  • Обработка на месте обычно невозможна или нецелесообразна — это баг, который нужно исправить.
  • Компилятор не требует явной обработки.
// Непроверяемое исключение — программист передал недопустимый аргумент
public void setDiscount(double discount) {
    if (discount < 0 || discount > 1) {
        throw new IllegalArgumentException("Discount must be between 0 and 1");
    }
    this.discount = discount;
}

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

Ответ 18+ 🔞

О, слушай, а вот это, блядь, тема, про которую можно дохуя спорить, но на самом деле всё просто, как три копейки. Выбор между checked и unchecked исключениями — это не просто так, сука, "ой, а давайте кину вот это". Это про ответственность, ёпта. Кто за что в ответе?

Проверяемые исключения (checked, типа IOException) — это когда ты, сука, предупреждаешь всех заранее: "Эй, народ, тут может случиться такая вот ожидаемая хуйня, будьте готовы!" Это часть контракта метода, блядь.

  • Когда юзать? Когда ошибка — это нормальная, ожидаемая часть работы, а не пиздец. Файл не нашли? Сеть отвалилась? Пользователь ввёл хуйню в конфиг? Да, бывает, сука. Жизнь такая.
  • Кто отвечает? Тот, кто вызывает твой метод. Компилятор ему в ебальник тычет: "Мужик, либо обработай эту ситуацию в try-catch, либо сам объяви, что кидаешь её дальше (throws). Решай, нахуй, что делать". Клиентский код может и должен как-то отреагировать.
// Проверяемое исключение. Говоришь всем: "Братан, файл может и не быть, не удивляйся"
public String readConfigFile(String path) throws IOException {
    return Files.readString(Paths.get(path)); // Может выстрелить, и это ок
}

Непроверяемые исключения (unchecked, наследники RuntimeException) — это уже, блядь, крик души: "ААА, КТО ТУТ УРОД ПРОГРАММУ ПИСАЛ?!" Это про ошибки в логике, про пиздец в состоянии программы.

  • Когда юзать? Когда наступил на грабли, которые сам же и разложил. Передал null туда, где он не жилец. Делишь на ноль. Индекс за границы массива полез. Это баг, ёпта. Ошибка программиста.
  • Кто отвечает? Тот, кто этот баг допустил. Обрабатывать это на месте — обычно бесполезно. Надо не try-catch писать, а идти чинить свой кривой код. Компилятор тебя за руку не ловит — ты сам себе злой буратино.
// Непроверяемое исключение. Это пиздец, а не ошибка.
public void setDiscount(double discount) {
    if (discount < 0 || discount > 1) {
        // Кричишь тому, кто это вызвал: "Ты чё, больной? Откуда у тебя скидка 200%?"
        throw new IllegalArgumentException("Discount must be between 0 and 1");
    }
    this.discount = discount;
}

Короче, практическое правило, которое даже обезьяна поймёт:

  • Checked (проверяемые) — для проблем, которые можно пережить. "Файла нет? Ну ок, спросим у пользователя путь ещё раз".
  • Unchecked (непроверяемые) — для пиздеца, который надо чинить. "На ноль делим? Да иди ты нахуй, исправляй свой алгоритм".

Всё. А то начнёшь IllegalArgumentException в throws пихать — выглядеть будешь как манда с ушами.