Что такое исключение
Исключение (Exception) — это событие, которое прерывает нормальный ход выполнения программы.
Когда возникает ошибка, Java создаёт объект класса Throwable и передаёт его в runtime-среду (JVM).
Если исключение не перехвачено (try-catch), программа завершается с ошибкой.
Иерархия Throwable
java.lang.Object
└── java.lang.Throwable
├── Exception
│ ├── RuntimeException
│ └── ... (другие checked исключения)
└── Error📗 Объяснение ветвей:
| Класс | Назначение |
|---|---|
Throwable | Базовый класс для всех ошибок и исключений |
Error | Ошибки JVM (не нужно обрабатывать вручную) — например, OutOfMemoryError, StackOverflowError |
Exception | Исключения, которые можно (и нужно) обрабатывать |
RuntimeException | Исключения времени выполнения (unchecked) — NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException и др. |
Checked vs Unchecked Exceptions
| Тип | Пример | Когда возникает | Нужно ли объявлять в throws | Обрабатывается? |
|---|---|---|---|---|
| Checked | IOException, SQLException, FileNotFoundException | Ошибки, предсказуемые на этапе компиляции (например, при работе с файлами, сетью) | ✅ Да | Обязательно (try-catch или throws) |
| Unchecked (Runtime) | NullPointerException, IndexOutOfBoundsException, ArithmeticException | Ошибки, возникающие во время выполнения (обычно из-за багов) | ❌ Нет | Можно обрабатывать, но не требуется |
📙 Пример: Checked Exception
import java.io.FileReader;
import java.io.IOException;
public class CheckedExample {
public static void main(String[] args) {
try {
FileReader reader = new FileReader("data.txt");
reader.read();
reader.close();
} catch (IOException e) {
System.out.println("Ошибка при чтении файла: " + e.getMessage());
}
}
}💡 Без блока try-catch компилятор не даст запустить код, потому что FileReader выбрасывает IOException.
📙 Пример: Unchecked Exception
public class UncheckedExample {
public static void main(String[] args) {
int[] nums = {1, 2, 3};
System.out.println(nums[5]); // ArrayIndexOutOfBoundsException
}
}💡 Можно скомпилировать, но при запуске получим ошибку во время выполнения.
Блоки try, catch, finally
✅ Основной синтаксис
try {
// код, который может выбросить исключение
} catch (ExceptionType e) {
// обработка исключения
} finally {
// выполняется всегда, независимо от наличия исключения
}📙 Пример:
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Деление на ноль!");
} finally {
System.out.println("Завершение операции");
}Вывод:
Деление на ноль!
Завершение операции
💡 finally выполняется всегда, даже если в catch есть return.
try-with-resources (Java 7+)
Назначение:
Автоматически закрывает ресурсы (например, файлы, потоки, соединения), реализующие интерфейс AutoCloseable.
Синтаксис:
try (FileReader reader = new FileReader("data.txt")) {
int c = reader.read();
} catch (IOException e) {
e.printStackTrace();
}💡 После выхода из try метод reader.close() вызывается автоматически, даже при исключении.
📍 Работает с любым объектом, реализующим AutoCloseable или Closeable.
Пример с JDBC:
try (Connection conn = DriverManager.getConnection(url);
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}Ключевые слова throw и throws
throw — выбрасывает исключение вручную
if (age < 0) {
throw new IllegalArgumentException("Возраст не может быть отрицательным!");
}💡Используется для генерации ошибок в коде или валидации данных.
throws — объявляет, что метод может выбросить исключение
void readFile(String path) throws IOException {
FileReader reader = new FileReader(path);
}💡Объявление throws обязательно для checked exceptions, если они не перехватываются внутри метода.
Множественные catch блоки
try {
FileReader reader = new FileReader("file.txt");
int x = 10 / 0;
} catch (FileNotFoundException e) {
System.out.println("Файл не найден");
} catch (ArithmeticException e) {
System.out.println("Ошибка деления");
} catch (Exception e) {
System.out.println("Общая ошибка");
}📍Блоки catch проверяются сверху вниз, от более конкретных к более общим.
Множественный catch (Java 7+)
Если нужно обработать несколько исключений одинаковым образом, можно объединить их:
try {
// ...
} catch (IOException | SQLException e) {
e.printStackTrace();
}Создание собственных исключений
Можно создать собственное исключение, унаследовавшись от Exception или RuntimeException.
Checked custom exception:
class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
}Unchecked custom exception:
class MyRuntimeException extends RuntimeException {
public MyRuntimeException(String message) {
super(message);
}
}📍Разница:
- Наследуешь
Exception→ нужно объявлятьthrows. - Наследуешь
RuntimeException→ можно не объявлять.
Типичные ошибки
❌ Проглатывание исключений:
try {
doSomething();
} catch (Exception e) {
// пусто — плохо!
}✅ Лучше:
try {
doSomething();
} catch (Exception e) {
log.error("Ошибка при выполнении", e);
throw e; // или обернуть в собственное исключение
}❌ Неверный порядок catch:
try { ... }
catch (Exception e) { ... }
catch (IOException e) { ... } // недостижимый код✅ Правильно — от частного к общему.
⚙️Best Practices
- ✅ Используй
try-with-resourcesдля любых IO/JDBC операций. - ✅ Лови только те исключения, которые можешь обработать осмысленно.
- ✅ Не используй
ExceptionилиThrowableвcatchбез причины. - ✅ Создавай собственные исключения для бизнес-логики.
- ✅ Не используй исключения для обычного контроля потока.
- ✅ Всегда логируй ошибки (
Logger,SLF4J,Logbackи т. д.).