JavaRush /Курсы /JAVA 25 SELF /Сложная обработка исключений и лучшие практики

Сложная обработка исключений и лучшие практики

JAVA 25 SELF
24 уровень , 3 лекция
Открыта

1. Множественный catch: обработка разных исключений

В реальных программах один и тот же блок кода может выбрасывать разные типы исключений. Например, при чтении файла может возникнуть как FileNotFoundException, так и IOException, а при парсинге данных — ещё и NumberFormatException. Чтобы корректно обработать каждую ситуацию, в Java можно использовать несколько блоков catch подряд.

Синтаксис

try {
    // опасные операции
} catch (FileNotFoundException e) {
    System.out.println("Файл не найден: " + e.getMessage());
} catch (IOException e) {
    System.out.println("Ошибка ввода-вывода: " + e.getMessage());
} catch (NumberFormatException e) {
    System.out.println("Некорректный формат числа: " + e.getMessage());
}

Важный момент:
Блоки catch должны идти от более специфичных к более общим! Если сначала написать catch (Exception e), то все остальные блоки станут недостижимыми, и компилятор выдаст ошибку.

Почему это важно?

  • Специфичная обработка: Можно по-разному реагировать на разные ошибки (например, предложить выбрать другой файл или повторить ввод).
  • Читаемость: Код становится понятнее — видно, какие ошибки ожидаются и как они обрабатываются.

2. catch с несколькими типами (multi-catch)

Иногда для разных исключений нужна одинаковая обработка. Например, вы хотите просто вывести сообщение об ошибке или залогировать её, независимо от того, была это ошибка чтения файла или преобразования числа.

С Java 7 появился синтаксис multi-catch, который позволяет объединить несколько типов исключений в одном блоке:

try {
    // опасная операция
} catch (IOException | NumberFormatException e) {
    System.out.println("Ошибка при обработке файла или числа: " + e.getMessage());
}

Как это работает:

  • Через вертикальную черту (|) указываются типы исключений.
  • Переменная e будет иметь тип самого общего базового класса (обычно Exception).
  • Внутри блока нельзя присваивать новое значение переменной e — она автоматически считается final.

Пример:

try {
    BufferedReader reader = new BufferedReader(new FileReader("numbers.txt"));
    String line = reader.readLine();
    int number = Integer.parseInt(line);
    System.out.println("Число: " + number);
    reader.close();
} catch (IOException | NumberFormatException e) {
    System.out.println("Ошибка: " + e.getMessage());
}

3. Лучшие практики обработки исключений

Не подавляйте исключения

Плохо:

try {
    // что-то опасное
} catch (Exception e) {
    // ничего не делаем!
}

Почему это плохо?
Пустой блок catch "глушит" ошибку — вы теряете информацию о причине сбоя, и программа становится неотлаживаемой.

Лучше: хотя бы выведите сообщение или залогируйте ошибку.

catch (Exception e) {
    e.printStackTrace();
}

Если вы не можете обработать исключение — пробросьте его дальше:

catch (IOException e) {
    throw e; // или throw new RuntimeException(e);
}

Бросайте наиболее специфичные исключения

Если вы пишете свои методы или API, всегда бросайте максимально конкретные исключения, а не просто Exception или RuntimeException. Это делает ваш код и интерфейс понятнее для других разработчиков.

Пример:

public void withdraw(double amount) throws InsufficientFundsException {
    if (amount > balance) {
        throw new InsufficientFundsException("Недостаточно средств");
    }
    // ...
}

Не используйте исключения для управления потоком программы

Исключения предназначены для обработки исключительных ситуаций — то есть ошибок, которые не должны происходить в нормальном ходе работы программы. Не используйте их для обычной логики (например, для выхода из цикла или проверки условий).

Плохо:

try {
    while (true) {
        String line = reader.readLine();
        if (line == null) break;
        // обработка строки
    }
} catch (Exception e) {
    // используем исключение для выхода из цикла — плохо!
}

Хорошо:

String line;
while ((line = reader.readLine()) != null) {
    // обработка строки
}

4. Практические примеры

Пример: обработка разных ошибок по-разному

try {
    BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
    String line = reader.readLine();
    int number = Integer.parseInt(line);
    System.out.println("Число: " + number);
    reader.close();
} catch (FileNotFoundException e) {
    System.out.println("Файл не найден!");
} catch (IOException e) {
    System.out.println("Ошибка чтения файла!");
} catch (NumberFormatException e) {
    System.out.println("В файле не число!");
}

Пример: multi-catch для одинаковой обработки

try {
    // что-то опасное
} catch (IOException | NumberFormatException e) {
    System.out.println("Ошибка: " + e.getMessage());
}

5. Важные нюансы и типичные ошибки

Ошибка №1: Неправильный порядок блоков catch. Сначала должны идти более специфичные исключения, а потом — общие. Иначе до широкого блока выполнение никогда не дойдёт.

Ошибка №2: Использование родственных типов в multi-catch. Например, catch (IOException | Exception e) не скомпилируется, потому что IOException наследуется от Exception.

Ошибка №3: Попытка изменить переменную e в multi-catch. В этом случае e считается final — присвоить ей новое значение нельзя.

Ошибка №4: Пустые catch-блоки. Игнорирование ошибок приводит к "тихим" багам. Минимум — выводите сообщение или логируйте исключение.

Ошибка №5: Ловля всех Exception подряд. Использование catch (Exception e) скрывает реальные проблемы и усложняет отладку. Лучше ловить только ожидаемые исключения.

1
Задача
JAVA 25 SELF, 24 уровень, 3 лекция
Недоступна
Финансовый отчёт: Точная диагностика проблем с данными
Финансовый отчёт: Точная диагностика проблем с данными
1
Задача
JAVA 25 SELF, 24 уровень, 3 лекция
Недоступна
Настройки игры: Единая реакция на сбои загрузки
Настройки игры: Единая реакция на сбои загрузки
1
Задача
JAVA 25 SELF, 24 уровень, 3 лекция
Недоступна
Секретный архив: Приоритет доступа к конфиденциальным данным
Секретный архив: Приоритет доступа к конфиденциальным данным
1
Задача
JAVA 25 SELF, 24 уровень, 3 лекция
Недоступна
Сервис логирования: Ни одна ошибка не должна быть потеряна!
Сервис логирования: Ни одна ошибка не должна быть потеряна!
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ