Ответ
Различие основано на обязательности обработки на этапе компиляции.
| Критерий | Checked Exceptions (Проверяемые) | Unchecked Exceptions (Непроверяемые / Runtime) |
|---|---|---|
| Наследование | Классы, наследующие от java.lang.Exception, но не от RuntimeException. |
Классы, наследующие от java.lang.RuntimeException (а она — от Exception). |
| Проверка компилятором | Да. Компилятор требует либо обработать исключение в try-catch, либо объявить в throws сигнатуре метода. |
Нет. Компилятор не требует их явного объявления или обработки. |
| Когда возникают | Внешние, часто восстанавливаемые условия, на которые программа может повлиять (отсутствие файла, разрыв сети, ошибка БД). | Внутренние ошибки программиста или логики приложения (обращение к null, неверный индекс массива, ошибка бизнес-логики). |
| Примеры | IOException, SQLException, ClassNotFoundException, FileNotFoundException. |
NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException, ArithmeticException. |
| Best Practice | Использовать для ошибок, которые разумно ожидать и от которых вызывающий код может восстановиться. | Использовать для ошибок, которые указывают на баг в программе и от которых обычно нельзя корректно восстановиться. |
Пример кода:
// CHECKED Исключение: Компилятор заставит его обработать.
public String readConfigFile(String path) throws IOException { // Объявляем в throws
return Files.readString(Path.of(path)); // Может выбросить FileNotFoundException (checked)
}
// Или обрабатываем:
public String readConfigFileSafe(String path) {
try {
return Files.readString(Path.of(path));
} catch (IOException e) { // Ловим checked исключение
return "default"; // Восстанавливаемся
}
}
// UNCHECKED Исключение: Компилятор не проверяет.
public int calculateDiscount(int price, int percent) {
if (percent < 0 || percent > 100) {
// Ошибка программиста/логики. Бросаем unchecked исключение.
throw new IllegalArgumentException("Процент должен быть от 0 до 100");
}
return price * percent / 100;
}
// Вызывающий код может, но не обязан, ловить его.
public void applyDiscount() {
try {
calculateDiscount(100, 150); // Выбросит IllegalArgumentException
} catch (IllegalArgumentException e) {
System.err.println("Неверные входные данные: " + e.getMessage());
}
}
Современный подход (с Java 8+): Часто предпочтение отдается unchecked-исключениям, чтобы не загромождать код. Checked-исключения уместны, когда вызывающая сторона действительно может предпринять осмысленные действия для восстановления.
Ответ 18+ 🔞
Давай разберём эту дичь, которую в академиях называют "исключениями". Сидишь ты такой, пишешь код, всё летает, и тут — бац! — всё падает. Вот это и есть исключения, только в джаве их ещё и на два лагеря поделили, будто на войне.
Смотри, вся суть в том, обязан ли компилятор тебе мозги выносить или нет.
| Критерий | Checked Exceptions (Проверяемые) | Unchecked Exceptions (Непроверяемые / Runtime) |
|---|---|---|
| От кого наследуются | От java.lang.Exception, но НЕ от RuntimeException. |
От java.lang.RuntimeException (а она, блядь, сама от Exception). |
| Компилятор дрочит? | Овердохуища! Он как мамаша-истеричка: "Либо обработай в try-catch, либо объяви в throws, иначе я тебя не скомпилирую, мудак!" |
Похуй. Компилятор смотрит на это как на твои личные проблемы. Не хочешь ловить — не лови. Упадешь — сам виноват. |
| Когда вылезают | Когда что-то пошло не так снаружи, и с этим, в теории, можно что-то сделать. Файл не найден, сеть отвалилась, база данных послала тебя нахуй. | Когда ты сам, как обезьяна с гранатой, накосячил внутри логики. Обратился к null, полез за границу массива, передал в метод какую-то дичь. |
| Примеры | IOException, SQLException, ClassNotFoundException. |
NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException. |
| Как жить с этим | Использовать, только если ты реально думаешь, что вызывающий код сможет с этой ошибкой что-то поделать (например, спросить у пользователя другой путь к файлу). | Использовать для всего остального. Если ошибка — это твой косяк или невалидные данные, от которых не оправиться. |
Ну и примеры, чтобы совсем пиздец стало понятно:
// CHECKED исключение. Компилятор будет орать, пока не сделаешь как он хочет.
public String readConfigFile(String path) throws IOException { // Объявляем в throws, типа "предупреждаю!"
return Files.readString(Path.of(path)); // Может выбросить FileNotFoundException
}
// Или обрабатываем на месте:
public String readConfigFileSafe(String path) {
try {
return Files.readString(Path.of(path));
} catch (IOException e) { // Ловим эту проверяемую заразу
return "default"; // И как-то выкручиваемся
}
}
// UNCHECKED исключение. Полная анархия, делай что хочешь.
public int calculateDiscount(int price, int percent) {
if (percent < 0 || percent > 100) {
// Ты чё, больной? Процент не может быть таким. Получай unchecked исключение!
throw new IllegalArgumentException("Процент должен быть от 0 до 100, а не " + percent);
}
return price * percent / 100;
}
// А вызывающий код может быть похуистом:
public void applyDiscount() {
try { // А может и не быть этого try-catch, компилятору всё равно
calculateDiscount(100, 150); // Выбросит IllegalArgumentException
} catch (IllegalArgumentException e) {
System.err.println("Чувак, ты что-то попутал: " + e.getMessage());
}
}
А теперь модный тренд, ёпта: Сейчас многие считают, что checked-исключения — это пережиток, который только код пухлым делает. Чаще кидают unchecked, чтобы не засирать сигнатуры методов этими throws. Checked оставляют только для ситуаций, где без них реально никак — когда ошибка ожидаемая и от неё можно по-человечески оправиться. А если всё летит в тартарары — значит, так и надо, пусть падает.