It boils down to the different types of exceptions there actually are.
Checked exceptions (that is, exception classes that extend Exception
) are typically errors you can recover from.
Unchecked exceptions (that is, exception classes that explicitly extend RuntimeException
) are those that indicate an error in either expected behavior or program state. You wouldn't get a NullPointerException
if the state of an object wasn't null
when you dereferenced it, of course.
Blanket-catching everything - either Exception
or Throwable
, which is far worse - is not a good practice because you're assuming that you can recover from any exceptional behavior. There are some cases in which you shouldn't, or realistically can't (i.e. OutOfMemoryError
for catch(Throwable t)
). Further, catching runtime exceptions indicates a code smell; it means that you're covering up a coding error.
Be explicit about what it is you're catching.
Aside: Yes, catch Exception
will also catch RuntimeException
, since Exception
is a superclass of RuntimeException
. Just the same, Throwable
will catch Exception
and Error
, which is why it's worse to write catch(Throwable t)
.