В чём разница между checked и unchecked исключениями в Java?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Checked и Unchecked исключения в Java
Основное различие
В Java все исключения делятся на две категории: checked (проверяемые) и unchecked (непроверяемые). Различие между ними принципиально — оно касается того, как компилятор проверяет обработку исключений.
Checked исключения — это исключения, которые компилятор ОБЯЗЫВАЕТ вас обрабатывать. Если метод выбрасывает checked исключение, вы ДОЛЖНЫ либо перехватить его в try-catch блоке, либо переопределить этот метод с указанием throws в сигнатуре.
Unchecked исключения — это исключения, проверка которых выполняется только во время выполнения программы. Компилятор НЕ обязывает вас их обрабатывать, хотя вы можете это сделать.
Иерархия исключений
java.lang.Throwable
├── java.lang.Exception
│ ├── CheckedException (checked)
│ │ ├── IOException
│ │ ├── SQLException
│ │ ├── FileNotFoundException
│ │ └── ...
│ └── RuntimeException (unchecked)
│ ├── NullPointerException
│ ├── ArrayIndexOutOfBoundsException
│ ├── ArithmeticException
│ ├── ClassCastException
│ └── ...
└── java.lang.Error (unchecked)
├── OutOfMemoryError
├── StackOverflowError
└── ...
Ключевой момент: если исключение наследует от RuntimeException или Error — это unchecked, если наследует непосредственно от Exception — это checked.
Checked исключения
Характеристики:
- Наследуют от
java.lang.Exception(но не от RuntimeException) - Компилятор проверяет их обработку
- Должны быть явно обработаны или объявлены в throws
- Используются для восстанавливаемых ошибок (expected errors)
Примеры:
- IOException — проблемы с входом-выходом
- SQLException — ошибки БД
- FileNotFoundException — файл не найден
- ClassNotFoundException — класс не найден
- InterruptedException — поток был прерван
Обработка checked исключений:
// Способ 1: перехват в try-catch
public void readFile() {
try {
FileInputStream fis = new FileInputStream("file.txt");
// читаем данные
} catch (FileNotFoundException e) {
System.out.println("Файл не найден: " + e.getMessage());
}
}
// Способ 2: объявление в throws
public void readFile() throws FileNotFoundException {
FileInputStream fis = new FileInputStream("file.txt");
// читаем данные
}
// Способ 3: try-with-resources (автоматическое закрытие ресурсов)
public void readFile() throws IOException {
try (FileInputStream fis = new FileInputStream("file.txt")) {
// читаем данные
} // fis закроется автоматически
}
Unchecked исключения
Характеристики:
- Наследуют от
java.lang.RuntimeExceptionилиjava.lang.Error - Компилятор НЕ требует их явной обработки
- Возникают из-за логических ошибок в коде
- Используются для неожиданных/невосстанавливаемых ошибок
Примеры:
- NullPointerException — обращение к методу/полю null объекта
- ArrayIndexOutOfBoundsException — выход за границы массива
- ArithmeticException — деление на ноль
- ClassCastException — неверное приведение типа
- IllegalArgumentException — недопустимое значение аргумента
Примеры unchecked исключений:
// NullPointerException
public void processString(String str) {
int length = str.length(); // если str == null, то NPE
}
// ArrayIndexOutOfBoundsException
public void getElement(int[] arr, int index) {
int value = arr[index]; // если index вне границ массива
}
// ArithmeticException
public int divide(int a, int b) {
return a / b; // если b == 0, то ArithmeticException
}
// ClassCastException
public void process(Object obj) {
String str = (String) obj; // если obj не String
}
// Unchecked исключения можно обрабатывать, но не обязательно
public int safeDivide(int a, int b) {
try {
return a / b;
} catch (ArithmeticException e) {
System.out.println("Деление на ноль!");
return 0;
}
}
Сравнительная таблица
| Параметр | Checked | Unchecked |
|---|---|---|
| Наследование | Exception (не RuntimeException) | RuntimeException, Error |
| Проверка компилятором | ДА | НЕТ |
| Обязательная обработка | ДА | НЕТ |
| Когда возникает | Ожидаемые ошибки | Логические ошибки |
| try-catch требуется | Обязательно | Опционально |
| Примеры | IOException, SQLException | NullPointerException, ArithmeticException |
Создание собственных исключений
// Checked исключение
public class InvalidEmailException extends Exception {
public InvalidEmailException(String message) {
super(message);
}
}
// Unchecked исключение
public class InvalidAgeException extends RuntimeException {
public InvalidAgeException(String message) {
super(message);
}
}
public class User {
public void setEmail(String email) throws InvalidEmailException {
if (!email.contains("@")) {
throw new InvalidEmailException("Email должен содержать @");
}
}
public void setAge(int age) {
if (age < 0) {
throw new InvalidAgeException("Возраст не может быть отрицательным");
}
}
}
Когда использовать какой тип
Используй checked исключения когда:
- Ошибка может быть восстановлена (например, повтор попытки)
- Это ожидаемое условие (например, файл не найден)
- Вызывающий код ДОЛЖЕН знать об этом и обработать
Используй unchecked исключения когда:
- Это программная ошибка (логическая ошибка)
- Невозможна автоматическая обработка
- Это непредвиденная ситуация
Лучшие практики
// ✅ Хорошо: используем checked для восстанавливаемых ошибок
public void loadConfig() throws ConfigurationException {
// читаем конфиг из файла
}
// ✅ Хорошо: используем unchecked для логических ошибок
public void setUserId(int id) {
if (id <= 0) {
throw new IllegalArgumentException("ID должен быть > 0");
}
}
// ❌ Плохо: слишком общий catch
try {
// код
} catch (Exception e) { // ловит всё!
e.printStackTrace();
}
// ✅ Хорошо: ловим конкретное исключение
try {
// код
} catch (IOException e) {
logger.error("Ошибка ввода-вывода", e);
// обработка
}
Вывод
Понимание разницы между checked и unchecked исключениями критично для правильной обработки ошибок в Java. Checked исключения обеспечивают безопасность типов и гарантируют, что вы не забудете обработать известные ошибки, а unchecked исключения помогают выявлять логические ошибки. Правильный выбор типа исключения делает код более надёжным и легче поддерживаемым.