Checked and Unchecked Exceptions in Java

February 8, 2011

Java has two types of exceptions – checked and unchecked. In short – checked are meant for cases when the developer can reasonably recover from the exception, while unchecked exceptions are programming errors that can’t be dealt with. This article explains when to use which.

But it is not that simple – checked exceptions are making the code “uglier”. They force the developer to write try/catch blocks or to rethrow the exception. But rethrowing hides another problem – some exceptions should not cross module boundaries. The most common thing to do when you are forced to catch a checked exception, which you have no idea what to do with, is to simply wrap it in a RuntimeException and rethrow it.

Actually, it might not be the most common – especially novice programmers tend to swallow exceptions, with empty catch blocks. Log & rethrow leads to doubled stacktraces sometimes, if there is some general layer for exception handling. Anyway, there are multiple bad practices here that lead to code that’s hard to debug and maintain.

Some say checked exceptions should be eliminated completely, given the verbosity, tediousness and error-proneness they introduce. C# does not have checked exceptions at all. Of course eliminating them should take into account backward compatibility.

I, however, believe the decision to have these two types of exceptions has its plus(es). It forces the developer to think that an exception is likely to happen in this situation, so he must take measures. The API declares that it will throw exceptions and the developer sees this compile-time. It enforces compile-time safety. You should not wait until the code goes to production to discover that something might fail. Javadoc? Well, a good option to say that, but I bet no one will read the javadoc until the exception actually happens.

So, how to have the “best of both worlds” ? I had a bizarre idea (explained in details here) for APIs to define two interfaces (linked through inheritance, so that only one interface is actually supported), and providing a way, through a factory, to get either an implementation whose methods throw checked exceptions, or one that wraps the checked exceptions into unchecked ones. It may be viable, it may be stupid, I can’t tell. For now it just looks strange.

But the above is a workaround at best. Then another idea came – introduce @RethrowExceptions annotation on methods. It will tell the compiler that in this method you don’t want to handle checked exceptions, but you also don’t want to declare them to be thrown. (The name of the annotation can be improved). In the simplest implementation that comes to my mind this can simply tell the compiler to surround the whole method body with try {..} catch (Exception ex) { throw new RuntimeException(ex);}. The benefits:

  • you are still warned by the compiler that the method you are using can throw an exception and you must think of handling it
  • you don’t make your code ugly by needless try/catches. And you don’t force your callers to think what to do with the exception
  • the possibility of swallowing the exception is decreased.

So in short – such an annotation would mark a method as one that is unable to handle the exception and does not want to propagate this decision to its callers.

This idea sounds less bizarre. I guess it can be implemented even now, using a compiler plug-in. Or perhaps it is already implemented in something like project lombok?

If you find the content interesting, you can subscribe and get updates


6 Responses to “Checked and Unchecked Exceptions in Java”

  1. I wrote up a formal proposal for solving the checked exception hell that we have ended up in – – but Oracle rejected it.

  2. I see. Your “throws” syntax has the same idea as my annotation. Perhaps they didn’t like the syntactical changes. Or perhaps they’re Oracle :)

  3. For your @RethrowExceptions idea: the JVM doesn’t have the concept of a checked vs unchecked exception, so @RethrowExceptions wouldn’t even need to wrap the exception. It could just pretend it’s unchecked at that method.

    In fact, you can even throw a checked exception in an unchecked manner!

    1 public class Unchecked {
    3 @SuppressWarnings(“unchecked”)
    4 public static void uncheckedThrow(Exception exception) {
    5 Unchecked asUnchecked = new Unchecked();
    6 Unchecked raw = asUnchecked;
    7 raw.t = exception;
    8 asUnchecked.throwIt();
    9 }
    11 private T t;
    13 public void throwIt() throws T {
    14 throw t;
    15 }
    17 public static void main(String[] args) {
    18 Exception checked = new Exception();
    19 uncheckedThrow(checked);
    20 }
    21 }

  4. Ah yuck, that broke — not just the formatting, but the parameterizations.

  5. Hi Bozho,
    I like your @RethrowExceptions idea. Do you know if it’s implemented somewhere?

  6. Nope. I haven’t seen it.

Leave a Reply