Exception hierarchy
All exceptions descend from Throwable. Exception (checked) and RuntimeException (unchecked) are the two branches. Error (e.g. OutOfMemoryError) is for severe JVM problems you should never catch.
Throwable
├── Exception (checked, handle or declare)
│ └── IOException
└── RuntimeException (unchecked, programming bug)
└── NullPointerException
Design your hierarchy so callers can catch precisely what they understand.