Какова иерархия классов ошибок и исключений в Java?

Ответ

В Java все ошибки и исключения организованы в иерархию, корнем которой является класс Throwable. Понимание этой иерархии критично для корректной обработки ошибок.

graph TD
    A[Throwable] --> B[Error]
    A --> C[Exception]

    B --> B1[VirtualMachineError]
    B1 --> B2[OutOfMemoryError]
    B1 --> B3[StackOverflowError]
    B --> B4[LinkageError]

    C --> D[IOException]
    D --> D1[FileNotFoundException]
    C --> E[RuntimeException]
    E --> E1[NullPointerException]
    E --> E2[IllegalArgumentException]
    E --> E3[IndexOutOfBoundsException]
    C --> F[Прочие проверяемые исключения<br/>например, SQLException]

Ключевые ветви иерархии:

  1. Error и его подклассы:

    • Представляют критические системные ошибки, от которых приложение обычно не может восстановиться (например, нехватка памяти, сбой JVM).
    • Обрабатывать их, как правило, не нужно и не рекомендуется.
    • Примеры: OutOfMemoryError, StackOverflowError, NoClassDefFoundError.
  2. Exception и его подклассы:

    • Представляют исключительные ситуации, с которыми приложение может и должно уметь работать.

    • Делится на две основные категории:

    • Проверяемые исключения (Checked Exceptions):

      • Наследуются от Exception, но НЕ от RuntimeException.
      • Компилятор требует их обработки (через try-catch) или объявления в сигнатуре метода (throws).
      • Примеры: IOException, SQLException, ClassNotFoundException.
      • Используются для ожидаемых ошибок внешних условий (файл не найден, сетевой сбой).
    • Непроверяемые исключения (Unchecked Exceptions):

      • Наследуются от RuntimeException.
      • Компилятор не проверяет их обработку.
      • Примеры: NullPointerException, IllegalArgumentException, ArrayIndexOutOfBoundsException.
      • Обычно указывают на ошибки программирования (баги в коде).

Пример обработки с учётом иерархии:

try {
    // Код, который может выбросить разные исключения
    someRiskyOperation();
} catch (FileNotFoundException e) {
    // Обработка конкретного проверяемого исключения
    System.out.println("Файл не найден: " + e.getMessage());
} catch (IOException e) {
    // Более общая обработка всех IO-исключений
    System.out.println("Ошибка ввода-вывода: " + e.getMessage());
} catch (IllegalArgumentException e) {
    // Обработка непроверяемого исключения
    System.out.println("Неверный аргумент: " + e.getMessage());
} catch (Exception e) {
    // Универсальный обработчик для всех оставшихся Exception
    System.out.println("Произошла ошибка: " + e.getMessage());
} // Error-ы здесь не ловятся, и это правильно.

Ответ 18+ 🔞

А, смотри-ка, какая интересная хуйня вырисовалась! Ну, про ошибки в Java, да? Это ж как в жизни, блядь: есть проблемы, которые можно решить, а есть такие, от которых только в окно выпрыгивать.

Вот представь себе, что все наши косяки и просёбы — это огромное семейное древо, а во главе стоит дедушка Throwable. Старый, блядь, матерый, всех породил. И у него два сына, два отпрыска, которые друг на друга не похожи, как хуй на палец.

Первый сынок — Error. Это, блядь, натуральный отморозок. Представляет он не просто ошибки, а пиздец полный, от которого приложение обычно не оправляется. Ну, типа, память кончилась (OutOfMemoryError) или стек переполнился (StackOverflowError) — это как если бы тебе дом рухнул на голову. Ловить такое? Да зачем, блядь? Это ж как пытаться поймать падающий с неба кирпич — только руки сломаешь. Компилятор тебя даже не заставляет это делать. Просто смирись, что иногда всё идёт по пизде.

А второй сынок — Exception. Вот это уже более культурный товарищ. Ситуации исключительные, но с ними можно как-то договориться. И вот тут, сука, начинается самое интересное, потому что у Exception тоже два типа детей, и они как день и ночь.

  • Проверяемые (Checked). Это такие зануды, блядь. Наследуются от Exception, но НЕ от RuntimeException. Компилятор — этот дотошный зануда — смотрит на них и орёт: «Эй, ты, мудила! Ты либо обработай эту ошибку прямо здесь, в try-catch, либо объяви, что твой метод её выбрасывает (throws), а то я код не скомпилирую!». Это типа IOException (файлик не нашёл) или SQLException (база данных послала нахуй). Ожидаемые проблемы внешнего мира.
  • Непроверяемые (Unchecked). А вот это наши родные, блядь, отморозки! Наследуются от RuntimeException. Компилятор на них смотрит сквозь пальцы, мол, «разбирайтесь сами, ебланы». Это почти всегда наши с тобой косяки, баги, просчёты. NullPointerException (тыкаешь в пустоту), IllegalArgumentException (подал на вход какую-то хуйню), ArrayIndexOutOfBoundsException (полез куда не просили). Обрабатывать их, конечно, можно, но лучше бы код писать так, чтобы они не возникали, хитрая жопа.

Вот смотри, как это в коде выглядит, когда ты пытаешься со всем этим бардаком справиться:

try {
    // Пытаемся сделать что-то рискованное, типа прочитать файл или вызвать сомнительный метод
    someRiskyOperation();
} catch (FileNotFoundException e) {
    // Ловим конкретную, ожидаемую фигню: файла нет.
    System.out.println("Бля, файл-то потерялся: " + e.getMessage());
} catch (IOException e) {
    // А тут ловим уже всё, что связано с вводом-выводом, по-крупному.
    System.out.println("Что-то пошло не так с диском или сетью: " + e.getMessage());
} catch (IllegalArgumentException e) {
    // А вот это уже наша вина, программистская. Подсунули методу какую-то дичь.
    System.out.println("Ты че, мудак, аргумент кривой передал? " + e.getMessage());
} catch (Exception e) {
    // Ну а это — универсальная сетка для всего остального, что улетело.
    System.out.println("Хуй знает что случилось, но случилось: " + e.getMessage());
} // А Error-ы мы тут не ловим. И правильно, блядь. Пусть падают. Это уже не наша вина.

Короче, запомни, ёпта: Error — это пиздец, с ним не борются. Exception — это проблемы, с ними работают. А внутри Exception есть зануды-проверяемые (компилятор заставляет париться) и наши родные непроверяемые косяки (компилятор делает вид, что не заметил). Всё, как в жизни: одни проблемы требуют немедленного внимания, а на другие можно забить хуй, пока они тебе по ебалу не прилетели.