Как в Java обработать несколько исключений в одном блоке catch?

Ответ

Начиная с Java 7, в одном блоке catch можно перехватывать несколько исключений, разделяя их типы вертикальной чертой |.

Синтаксис:

try {
    // Код, который может выбросить разные исключения
    int num = Integer.parseInt(userInput); // Может выбросить NumberFormatException
    int result = 100 / num; // Может выбросить ArithmeticException
} catch (NumberFormatException | ArithmeticException e) {
    // Обработка для обоих типов исключений
    System.err.println("Некорректный ввод или математическая ошибка: " + e.getMessage());
    logger.log(Level.WARNING, "Ошибка обработки ввода", e);
}

Важные правила:

  1. Несвязанные исключения: Типы в мульти-catch должны быть несовместимыми по присваиванию (не находиться в отношении предок-потомок).
    • Допустимо: catch (IOException | SQLException e)
    • Недопустимо: catch (FileNotFoundException | IOException e) (т.к. FileNotFoundException — потомок IOException).
  2. Final переменная: Переменная исключения (e) является неявно final. Ей нельзя переназначить новое значение внутри блока catch.
  3. Цель использования: Устраняет дублирование кода, когда обработка для разных типов исключений идентична.

Пример с ресурсами и более сложной обработкой:

try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    String line = br.readLine();
    // ... обработка строки
} catch (FileNotFoundException e) {
    System.err.println("Файл не найден.");
} catch (IOException | SecurityException e) {
    // Общая обработка для ошибок ввода/вывода и нарушений безопасности
    System.err.println("Ошибка доступа или чтения файла: " + e.getClass().getSimpleName());
}

Ответ 18+ 🔞

А, слушай, смотри, с Java 7-й, блядь, придумали удобную хуйню — можно в один catch сразу несколько исключений ловить, через вот эту палку |. Ну, чтобы не писать одно и то же по десять раз, если обработка одинаковая.

Как это выглядит, сука:

try {
    // Код, который может выбросить разные исключения
    int num = Integer.parseInt(userInput); // Может выбросить NumberFormatException
    int result = 100 / num; // Может выбросить ArithmeticException
} catch (NumberFormatException | ArithmeticException e) {
    // Обработка для обоих типов исключений
    System.err.println("Некорректный ввод или математическая ошибка: " + e.getMessage());
    logger.log(Level.WARNING, "Ошибка обработки ввода", e);
}

Но тут, блядь, есть правила, которые надо помнить, а то наебнёшься:

  1. Исключения не должны быть роднёй. Их типы должны быть несовместимыми по присваиванию, то есть не предок и потомок.
    • Можно: catch (IOException | SQLException e) — два разных дядьки.
    • Нельзя, ёпта: catch (FileNotFoundException | IOException e) — потому что FileNotFoundException это дитё IOException. Это уже пиздец, компилятор тебе мозги вынесет.
  2. Переменная e — как девственница, final. Её нельзя переприсвоить внутри блока, хоть ты тресни. Она неявно final.
  3. Зачем это надо? Ну чтобы не копипастить один и тот же код обработки для разных исключений. Удобно же, блядь!

Вот ещё примерчик, посложнее, с ресурсами:

try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    String line = br.readLine();
    // ... обработка строки
} catch (FileNotFoundException e) {
    System.err.println("Файл не найден.");
} catch (IOException | SecurityException e) {
    // Общая обработка для ошибок ввода/вывода и нарушений безопасности
    System.err.println("Ошибка доступа или чтения файла: " + e.getClass().getSimpleName());
}

Вот так вот, в рот меня чих-пых, жить стало проще. Главное — не перепутай, кто кому кем приходится в иерархии исключений, а то получишь ошибку компиляции и волнение ебать.