В чем разница между checked и unchecked исключениями


В языке программирования Java исключения (exceptions) делятся на два основных типа: checked (проверяемые) и unchecked (непроверяемые). Эти типы отличаются тем, как и когда компилятор и программист обязаны обрабатывать исключения. Это деление связано с иерархией классов исключений и механизмом обработки ошибок в Java.

🔹 Иерархия исключений в Java

Все исключения в Java происходят от класса Throwable, который делится на два подтипа:

  • Error — ошибки времени выполнения, возникающие в виртуальной машине (например, OutOfMemoryError), не подлежат обработке.

  • Exception — обрабатываемые исключения, порождаемые логикой программы.

Класс Exception делится дальше:

Throwable

├── Error (не обрабатываются)

└── Exception

├── Checked exceptions (например, IOException, SQLException)

└── Unchecked exceptions (наследуются от RuntimeException)

✅ Checked исключения (проверяемые)

📌 Что это такое

Checked исключения — это исключения, которые проверяются компилятором на этапе компиляции. Это означает, что метод, который может выбросить checked исключение, обязан:

  • Либо явно указать его в сигнатуре с помощью throws.

  • Либо обработать через try-catch.

📚 Примеры checked исключений

  • IOException

  • SQLException

  • FileNotFoundException

  • ClassNotFoundException

  • InterruptedException

📌 Пример использования

import java.io.\*;
public class FileReaderExample {
public static void main(String\[\] args) {
try {
readFile("test.txt");
} catch (IOException e) {
System.out.println("Ошибка чтения файла: " + e.getMessage());
}
}
public static void readFile(String path) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(path));
String line = reader.readLine();
reader.close();
}
}

Если не написать throws IOException или try-catch, программа не скомпилируется.

📌 Особенности

  • Заставляют программиста явно думать об обработке ошибок.

  • Являются частью контракта метода.

  • Нарушение правил приводит к ошибке компиляции.

❌ Unchecked исключения (непроверяемые)

📌 Что это такое

Unchecked исключения — это исключения времени выполнения, происходящие от класса RuntimeException. Компилятор не требует их явно обрабатывать — ни через throws, ни через try-catch.

📚 Примеры unchecked исключений

  • NullPointerException

  • IllegalArgumentException

  • ArrayIndexOutOfBoundsException

  • ClassCastException

  • ArithmeticException

  • UnsupportedOperationException

📌 Пример использования

public class DivideExample {
public static void main(String\[\] args) {
int result = divide(10, 0); // java.lang.ArithmeticException
System.out.println(result);
}
public static int divide(int a, int b) {
return a / b;
}
}

Здесь деление на ноль приведёт к ArithmeticException, но компилятор не заставит нас её обрабатывать.

📌 Особенности

  • Необязательная обработка.

  • Чаще всего вызваны ошибками логики в коде.

  • Их обработка — решение разработчика, а не требование компилятора.

  • Программист может захотеть выбрасывать свои RuntimeException для указания на программную ошибку.

🧱 Сравнение: Checked vs Unchecked

Критерий Checked Exception Unchecked Exception
Наследование Наследуются от Exception, но не от RuntimeException Наследуются от RuntimeException
--- --- ---
Проверка компилятором Да Нет
--- --- ---
Обязательная обработка Да (try-catch или throws) Нет
--- --- ---
Примеры IOException, SQLException NullPointerException, ArithmeticException
--- --- ---
Тип ошибки Проблемы окружения (I/O, сеть и т.п.) Ошибки программной логики
--- --- ---
Ошибка компиляции при игнорировании Да Нет
--- --- ---

🧪 Кастомные исключения

Вы можете создать свои собственные checked и unchecked исключения:

Checked:
class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
}
Unchecked:
class MyUncheckedException extends RuntimeException {
public MyUncheckedException(String message) {
super(message);
}
}

🧠 Когда использовать какой тип

Использовать checked:

  • Когда ошибку можно ожидать и обработать корректно, например:

    • файл не найден

    • соединение с базой данных прервано

    • истёк таймаут

Использовать unchecked:

  • Когда ошибка вызвана неправильной логикой или некорректным использованием API:

    • передан null, где этого быть не должно

    • деление на 0

    • выход за пределы массива

Unchecked исключения предполагают, что ошибка не может быть "исправлена" программой, и её следует предотвратить на уровне логики.

📦 Примеры из стандартной библиотеки

Checked
public void readFile(String filename) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(filename));
// ...
}

Программист обязан обработать IOException.

Unchecked
List&lt;String&gt; list = new ArrayList<>();
list.get(1); // IndexOutOfBoundsException

Нет принуждения к обработке — это логическая ошибка.

📈 Обсуждение и критика

Некоторые разработчики считают, что:

  • Checked исключения перегружают код лишними try-catch.

  • Unchecked исключения делают код чище и короче.

  • Современные API (включая новые версии Java) часто избегают checked исключений (например, Streams API), предоставляя разработчику свободу.

Однако checked исключения полезны при работе с внешними ресурсами (файлы, сеть, базы данных), так как они заставляют учитывать возможные сбои.

📚 Checked исключения и API-контракты

Методы, объявляющие throws, фактически расширяют контракт, позволяя вызывающему коду знать, какие типы исключений могут быть выброшены.

Это особенно полезно при:

  • Проектировании библиотек и SDK.

  • Документировании поведения метода.

public void sendEmail() throws MessagingException {
// ...
}

Таким образом, checked исключения формируют часть API-дизайна, в отличие от unchecked, которые представляют ошибки исполнения.