I've always considered that runtime exceptions should represent programming errors (e.g. null
reference passed in when not expected, array index out of bounds, etc.) while checked exceptions should represent exceptional conditions in the environment that cannot be "coded away" (e.g. IOException
, SQLException
).
One violation of this is that sometimes you'll need to wrap what ought to be a checked exception in a RuntimeException, in order to satisfy the definition of an interface. As a brief example, you might have some snazzy implementation of java.util.List
that manages a distributed list between multiple machines. Clearly this would throw checked exceptions (probably some subclass of IOException
) if defined on its own, but the benefits of making this class implement List
is that clients can use it almost transparently, anywhere they use another list.
This can lead to what Joel terms a leaky abstraction, though, so it's important that your documentation is clear what exceptions can be thrown and what they mean! In this case I find a custom subclass of RuntimeException
to generally be clearer at communicating the root cause rather than trying to shoehorn it into an existing runtime exception class.