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

Ответ

Корневым классом всей иерархии исключений в Java является Throwable. От него наследуются два основных класса:

  1. Error — представляет критические системные ошибки (например, OutOfMemoryError, StackOverflowError), которые обычно не обрабатываются в прикладном коде.
  2. Exception — базовый класс для исключительных ситуаций, с которыми может столкнуться программа. От него, в свою очередь, наследуются:
    • Проверяемые исключения (checked), такие как IOException. Они должны быть либо обработаны в блоке try-catch, либо объявлены в сигнатуре метода с помощью throws.
    • Непроверяемые исключения (unchecked)RuntimeException и его подклассы (например, NullPointerException, IllegalArgumentException). Их обработка не является обязательной для компилятора.

Пример обработки:

try {
    // Код, который может выбросить исключение
    FileInputStream fis = new FileInputStream("file.txt");
} catch (FileNotFoundException e) { // Обработка проверяемого исключения
    System.err.println("Файл не найден: " + e.getMessage());
} catch (RuntimeException e) { // Обработка непроверяемого исключения
    System.err.println("Ошибка времени выполнения: " + e);
}

Ответ 18+ 🔞

А, ну это же про исключения в Java! Ёпта, классика, как этот Герасим с Муму, только без воды и с кодом. Слушай, давай разжую, как есть, без соплей.

Вот представь себе всю эту иерархию ошибок как ёбаную лестницу в подъезде. На самом верху, на чердаке, сидит дед по имени Throwable. Он, блядь, корень всего, прародитель. От него и пляшут.

У деда два сына, два отпрыска, хуй с горы.

Первый сын — Error. Это, сука, неадекватный алкаш-сосед, который может вломиться к тебе в квартиру и вырубить рубильник на всём этаже. OutOfMemoryError, StackOverflowError — это он. С ним не договоришься, его не обработаешь. Только вызывать ментов (JVM) и надеяться, что они его усмирят. В обычном коде на него забиваем болт, потому что если он пришёл — уже всё, пиздец, пиши пропало.

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

Первый внук — проверяемые исключения (checked). Например, IOException. Это как твоя бабка, которая звонит каждые пять минут: «А ты шапку надел? А ты файл проверил?». Компилятор — эта бабка. Он тебе не даст спокойно скомпилировать код, пока ты не пообещаешь, что либо обработаешь эту проблему (try-catch), либо публично признаешь, что твой метод может такое выкинуть (throws). Надоедливо, блядь, но зато безопасно.

Второй внук — непроверяемые исключения (unchecked), они же RuntimeException и его банда (NullPointerException, IllegalArgumentException). Это уже местные гопники. Могут возникнуть из ниоткуда, когда ты null попытаешься потрогать. Компилятор на них забивает хуй, он как будто говорит: «Сам дурак, разбирайся сам». Обрабатывать их не обязан, но если не обработаешь — получишь по ебалу в рантайме.

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

try {
    // Пытаемся сделать что-то опасное, как Герасим пойти на речку
    FileInputStream fis = new FileInputStream("file.txt");
} catch (FileNotFoundException e) { // Ловим проверяемое исключение — «файла нет!»
    System.err.println("Файл не найден: " + e.getMessage()); // «Муму, блядь, где ты?»
} catch (RuntimeException e) { // Ловим непроверяемое — вдруг что-то ещё пошло не так
    System.err.println("Ошибка времени выполнения: " + e); // «Да ёпта, что ещё?»
}

Вот и вся философия. Либо ты всё предусматриваешь и ловишь, либо летишь вниз с лестницы, как тот князь, с криком «Я в этот метод не ногой!». Выбирай, чувак.