A general approach to exceptions in Java

Checked vs. Unchecked Exceptions in Java. The topic is pretty much as controversial as it comes. The debate over when to use a unchecked (those that are subclasses of java.lang.RuntimeException) vs. a checked (those that do not extend RuntimeException) is as old as Java itself.

I’ve witnessed many a debate over the topic over the years. When to use unchecked ? Are checked exceptions even a good thing ? Everyone has a different opinion on the subject so I’ll attempt to explain a general approach that hopefully will be helpful to decide when to use one type of exception over the other.

Both checked and unchecked exceptions are useful

Yes, both exception types are useful. You will sometimes find extremes of people who will only use one or the other, but by doing this you will not be able to benefit from the unique properties of each type: Unchecked exceptions don’t obviously have to be declared as part of the method signature, so the exception does not need to be handled or exposed in all the method signatures up the call stack. Checked exceptions are the opposite, they force the caller to either deal with the exception or inform its caller that it needs to deal with it and so on. These are both unique characteristics that are useful in different circumstances.

When to use each type

Exceptions are thrown because there is some sort of error that the system cannot deal with. An error can be categorised as either “there is an error in the code” or “there is an error with the system’s operating environment”. These two categories can can distilled into “an error that can be prevented”, vs. “an error that the system has no control over”.

So, if the system was perfectly designed, i.e. no bugs, then the first type of exception (an unchecked exception, an error in the code) should never occur. These are RuntimeExceptions, since there is no point bothering the caller of your object with errors that should not occur ! Examples of these are NullPointerException (check for null !), ArrayIndexOutOfBoundsException (check the length of the array !) etc.

The other type of exception, checked exceptions, are completely out of the control of the system and clients should be forced to deal with them. Examples of these are JDBCException (you can’t control whether the database will be available), FileNotFoundException (sure, you can check to see if a file exists, but you can’t guarantee it’ll be there when you read it) and RemoteException (you can’t ensure that the remote service will be available or bug free).

Perfect code vs. perfect environment

So, in summary I follow the following rules: use unchecked exceptions for errors that can be prevented and checked for those that cannot. It can also be thought of like this: If you have perfect code there should be no runtime exceptions. If you have a perfect environment there should be no checked exceptions. Obviously neither of these are possible, this is why we need both types of exceptions.