Exception Hierarchy

Basic Java
≈ 2 min read

Exceptions have a common root

Exceptional situations in Java are represented by objects, and their types form a regular inheritance hierarchy. At its base is the Throwable class. Java can use objects of this class and its subclasses as exceptional situations.

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

Throwable has two main branches: Error and Exception. They are on the same level and represent different categories of problems.

Error and Exception are different branches

Error is used for serious runtime environment problems that an ordinary application generally does not try to treat as an expected situation. Examples from this branch include OutOfMemoryError and StackOverflowError.

Exception is the branch for situations that application code usually associates with the concept of an “exception.” It has many subclasses describing different kinds of problems.

Error is not a kind of Exception. Both classes, directly or through their branches, lead back to Throwable. So the statement “all errors are Exceptions” is incorrect.

Where RuntimeException fits

RuntimeException is located inside the Exception branch. Many familiar exceptions inherit from it: NullPointerException, IllegalArgumentException, IndexOutOfBoundsException, and others.

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

The position of RuntimeException in this hierarchy will later help explain why Java treats different groups of exceptions differently. We will cover checked and unchecked exceptions in detail in a separate topic.

The hierarchy follows normal inheritance rules

The familiar rules of polymorphism apply here: an object of a subclass can be stored in a variable whose type is one of its ancestors. For example, IllegalArgumentException is also a RuntimeException, Exception, and Throwable.

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

The higher a type is in the tree, the more different subclasses it groups together. That is why understanding this structure will matter later: exception-handling constructs rely not only on the specific class of a problem, but also on its place in the hierarchy.