← Назад к вопросам

Какие знаешь основные две группы в иерархии исключений?

2.3 Middle🔥 191 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Иерархия исключений в 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) позволяет мне создавать чистый, предсказуемый код с правильной обработкой ошибок.