Checked Exceptions suck?

Darren Hobbs: Checked Exceptions Don't (always) Suck. I agree with Darren's statement that checked exceptions are misused a lot. As a matter of fact, they're misused so much that I've come to the conclusion that, while great in theory, they do indeed suck in practice.

If you have a team of experienced and disciplined Java developers that truly understand how exception handling is supposed to work in Java, the distinction between checked and unchecked exceptions is great and really helps develop robust applications. Unfortunately, real-world teams typically don't work that way and many mistakes are made that turn the benefits of checked exceptions into a disadvantage.

Here's a list of the exception handling mistakes I've seen made most often:

  • Many (if not most) Java developers never create their own RuntimeException descendants, but instead make everything checked. This puts a huge burden on the caller to deal with all these exceptions. A method should only be declared to throw an Exception if its caller should be forced to (and can be expected to be able to) handle this exception. Program bugs on the other hand (like a method being called without its preconditions being met) should throw RuntimeExceptions.
  • Oftentimes, when forced to handle an exception they think will never happen, developers just put an empty catch-block in to satisfy the compiler. Then when this exception subsequently does happen, it is ignored and will probably cause the application to fail somewhere else. Trying to find the source of this other failure will then oftentimes prove to be a real nightmare.
  • Merely printing the error message (or stack-trace) on System.out in a catch-block is almost just as bad as ignoring it with an empty catch-block. This may help during development, but who watches the console in production? And even if someone does watch it 24/7, how acceptable is this kind of error-handling really to your users?
  • Code that catches an Exception, just to exit a method with a null return value. This is bad as it oftentimes results in a NullPointerException elsewhere.
  • Using a generic catch(Exception e) clause. This is often done by developers that are forced to deal with many different types of exceptions. The problem with this is that different exceptions tend to need to be handled differently. A NullPointerException for instance would need another handler than a SQLException. Also, by adding a generic catch(Exception e), you also automatically handle any future exceptions that may be thrown by new code being added to the try{} block later. This nullifies the main advantage of checked exceptions: being forced to handle them.
  • Entire applications in which every method catches every checked exception. Checked exceptions don't always need to be caught! If you don't know how to handle an exception in your method, but you can reasonably expect your caller to do so, just ignore it and mark your method to throws this exception.
  • Throwing a new exception-class from a catch-block without keeping a reference to the original exception. This effectively removes the original stack-trace, making it much harder to find the cause of the problem. Starting in JDK 1.4, the Throwable class has built-in support for wrapping a cause-exception. If you use an older JDK, keep a reference to the cause-exception in your exception class and override printStackTrace() (all three variants) to also print the stack trace of the original exception.
  • And last but not least: throwing RuntimeExceptions from an EJB without realizing the implications this has on the current transaction. When using Container Managed Transactions, RuntimeExceptions will automatically mark your current transaction for rollback, which is oftentimes not what you want. They also get wrapped in an EJBException by the container, preventing the client from easily being able to catch specific RuntimeExceptions.

The net result of all these potential problems is that Java's exception handling mechanism is typically poorly implemented, leading to fragile applications that are hard to debug when things go wrong.

Do I think the C# approach of making all exceptions unchecked is perfect? No I don't. There are clearly benefits to being able to force a method caller to deal with certain Exceptions. Unfortunately the theory of checked exceptions works better than the typical implementation of them.

TrackBack URL for this entry:

I agree with all these points, though with JDK 1.4, wouldn't you rather assert(false) than rethrow something as a runtimeexception if there really is a bug (something a caller would never be expected to handle - and a situation where you want your system to fail as fast as possible)?

Posted by Steve Conover at February 27, 2003 12:09 PM

I didn't mean to say just assert false, you might want to provide some helpful message to the assert...or a printstacktrace would probably do in that situation too.

Posted by Steve Conover at February 27, 2003 12:11 PM

For potential program bugs that are internal to your methods, I agree that using assert is oftentimes better than throwing a RuntimeException. You need to be careful with this though as assertions can be turned off (so your application may not check them), and failed assertions throw an Error, which may end up killing your entire application (since catch(Exception e) won't catch them) which is typically not what you want.

When checking method preconditions on the other hand, specific RuntimeException descendants are preferred.

See for deeper coverage on when assertions should and should not be used.

Posted by Luke Hutteman at February 28, 2003 1:14 AM

Checked Exceptions Are Important
Luke states that he has come to the "conclusion that, while great in theory, they[checked exceptions] do indeed suck in practice". I have to completely disagree with him. I tend to agree with Darren.

Trackback from _mindMeld at March 1, 2003 11:45 AM

Interesting, thanks for the URL.

Posted by Steve Conover at March 1, 2003 12:51 PM

Blog Explosion! As far as I can tell, it started with this article by Bruce Eckel. Darren Hobbs responded, which caused Luke Hutteman to comment. Les Stroud disagrees, and so Luke has to answer. Now, Gosling has responded, and here...

Trackback from Infloop at September 22, 2003 10:37 AM
This discussion has been closed. If you wish to contact me about this post, you can do so by email.