Иерархия исключений

Базовый Java
≈ 2 мин чтения

У исключений есть общий корень

Исключительные ситуации в Java представлены объектами, а их типы образуют обычную иерархию наследования. В её основе находится класс Throwable. Именно его объекты и объекты его подклассов Java может использовать как исключительные ситуации.

Object
└── Throwable
    ├── Error
    └── Exception
        └── RuntimeException

У Throwable две главные ветви: Error и Exception. Они находятся на одном уровне и обозначают разные категории проблем.

Error и Exception — разные ветви

Error используется для серьёзных проблем среды выполнения, с которыми обычное приложение, как правило, не пытается работать как с ожидаемой ситуацией. К этой ветви относятся, например, OutOfMemoryError и StackOverflowError.

Exception — ветвь для ситуаций, с которыми прикладной код обычно и связывает понятие «исключение». У неё много подклассов, описывающих разные виды проблем.

Error не является разновидностью Exception. Оба класса напрямую или через свои ветви восходят к Throwable. Поэтому фраза «все ошибки — это Exception» неверна.

Где находится RuntimeException

RuntimeException находится уже внутри ветви Exception. От него наследуются многие знакомые исключения: NullPointerException, IllegalArgumentException, IndexOutOfBoundsException и другие.

Exception
└── RuntimeException
    ├── NullPointerException
    ├── IllegalArgumentException
    └── IndexOutOfBoundsException

Положение RuntimeException в этой иерархии позже поможет понять, почему Java по-разному относится к разным группам исключений. Подробно checked и unchecked исключения разберём в отдельной теме.

Иерархия работает как обычное наследование

Здесь действуют уже знакомые правила полиморфизма: объект подкласса можно хранить в переменной типа его предка. Например, IllegalArgumentException одновременно является RuntimeException, Exception и Throwable.

RuntimeException first = new IllegalArgumentException("Wrong value");
Exception second = new IllegalArgumentException("Wrong value");
Throwable third = new IllegalArgumentException("Wrong value");

Чем выше тип находится в дереве, тем больше разных подклассов он объединяет. Именно поэтому понимание этой схемы понадобится дальше: конструкции работы с исключениями опираются не только на конкретный класс проблемы, но и на его место в иерархии.