Какие знаешь основные две группы в иерархии исключений?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Иерархия исключений в Java
Иерархия исключений в Java — это фундаментальная концепция обработки ошибок, которая я использую ежедневно в своей работе. Все исключения в Java наследуются от класса Throwable, который разделяется на две основные группы.
Основные две группы исключений
Первая группа: Exception (Проверяемые исключения)
Exception — это исключения, которые должны быть обработаны при компиляции. Компилятор Java явно требует, чтобы мы либо поймали такое исключение (try-catch), либо объявили его в сигнатуре метода (throws). Это исключения, которые предусмотрены программистом и ожидаются в нормальном потоке выполнения программы.
Примеры проверяемых исключений, которые я часто встречаю:
// IOException — исключение при работе с файлами и потоками
public void readFile(String path) throws IOException {
FileReader reader = new FileReader(path);
reader.close();
}
// SQLException — исключение при работе с БД
public void queryDatabase() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
}
// FileNotFoundException — подкласс IOException
public void loadConfig(String filename) throws FileNotFoundException {
InputStream is = new FileInputStream(filename);
}
// InterruptedException — при работе с потоками
public void sleepThread() throws InterruptedException {
Thread.sleep(1000);
}
Обработка проверяемых исключений:
public void processFile(String path) {
try {
FileReader reader = new FileReader(path);
int data = reader.read();
reader.close();
} catch (FileNotFoundException e) {
System.err.println("Файл не найден: " + e.getMessage());
} catch (IOException e) {
System.err.println("Ошибка при чтении файла: " + e.getMessage());
}
}
public void databaseOperation() {
try {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db");
// выполнение запроса
} catch (SQLException e) {
System.err.println("Ошибка БД: " + e.getSQLState());
} finally {
// закрытие ресурсов
}
}
Вторая группа: RuntimeException (Непроверяемые исключения)
RuntimeException — это исключения, которые не требуют явной обработки при компиляции. Они возникают во время выполнения программы из-за ошибок в логике кода. Компилятор не будет требовать их обработку, но игнорировать их опасно.
Основные непроверяемые исключения:
// NullPointerException — попытка обращения к методу null объекта
String str = null;
int length = str.length(); // выброс NPE
// ArrayIndexOutOfBoundsException — выход за границы массива
int[] array = {1, 2, 3};
int value = array[10]; // выброс исключения
// ClassCastException — неверное приведение типов
Object obj = "string";
Integer num = (Integer) obj; // выброс исключения
// NumberFormatException — невалидное преобразование в число
String str = "abc";
int num = Integer.parseInt(str); // выброс исключения
// IllegalArgumentException — неверный аргумент метода
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("Возраст не может быть отрицательным");
}
this.age = age;
}
// UnsupportedOperationException — операция не поддерживается
public void unsupportedMethod() {
throw new UnsupportedOperationException("Этот метод не реализован");
}
// ConcurrentModificationException — изменение коллекции во время итерации
List<String> list = new ArrayList<>();
list.add("a");
for (String item : list) {
list.remove(item); // выброс исключения
}
Иерархия визуально
Throwable
├── Exception (Checked)
│ ├── IOException
│ ├── SQLException
│ ├── FileNotFoundException (extends IOException)
│ ├── InterruptedException
│ └── RuntimeException (Unchecked)
│ ├── NullPointerException
│ ├── ArrayIndexOutOfBoundsException
│ ├── ClassCastException
│ ├── NumberFormatException
│ └── IllegalArgumentException
└── Error (Throwable, но не Exception)
├── StackOverflowError
├── OutOfMemoryError
└── VirtualMachineError
Важное уточнение про Error
Отдельно стоит отметить группу Error — это очень серьёзные ошибки, которые обычно невозможно восстановить (StackOverflowError, OutOfMemoryError). Мы их НЕ должны ловить.
Практический подход в коде
В моей практике я использую оба типа исключений правильно:
@Service
public class UserService {
// Проверяемое исключение — явно объявляю
public User loadUserFromFile(String filename) throws IOException {
FileReader reader = new FileReader(filename);
// парсинг файла
return user;
}
// Непроверяемое исключение — валидирую и выбрасываю
public void createUser(String email) {
if (email == null || email.isEmpty()) {
throw new IllegalArgumentException("Email не может быть пустым");
}
// создание пользователя
}
// Комбинирование обеих типов
public User importUsersFromDatabase(String connectionString)
throws SQLException {
if (connectionString == null) {
throw new IllegalArgumentException("Connection string required");
}
try {
Connection conn = DriverManager.getConnection(connectionString);
// выполнение запроса
return user;
} catch (SQLException e) {
throw new RuntimeException("Database error: " + e.getMessage(), e);
}
}
}
Когда использовать какой тип
Проверяемые исключения (Exception):
- Когда ошибка ожидается и восстановима (I/O, сеть, БД)
- Когда вызывающий код должен обработать ошибку
Непроверяемые исключения (RuntimeException):
- Когда ошибка вызвана ошибкой программиста
- Когда невозможно восстановиться во время выполнения
- Когда операция не требует обязательной обработки
Заключение
Понимание иерархии исключений критично для написания надёжного Java кода. Правильное различие между проверяемыми исключениями (Exception) и непроверяемыми исключениями (RuntimeException) позволяет мне создавать чистый, предсказуемый код с правильной обработкой ошибок.