Java Exceptions Should Be Interfaces

[Voting on JavaDesignFlaws page.]

In CheckedExceptionsAreOfDubiousValue and MessyExceptionHierarchy some very good points regarding problems with the Java exceptions are raised. However, I feel that many of the arguments on these pages slightly miss the point.

My standpoint is that CheckedExceptionsAreaGoodThing?. This, of course, as long as they are only used for exceptions beyond the programmer's control. This is an important design issue that is easy to get wrong. Even the Java designers do it. This does not mean they are bad. The potential exceptions that can be thrown from a method, for example IOException when trying to read from a file, is an important part of the method signature. Just as the read() function in C can return an error code, the FileInputStream.read() method can also fail, and this needs to be a part of the signature. I feel that many of the arguments against checked exceptions come from people who either doesn't understand what their purpose is, or have had the bad experience of working with an API that misuses CheckedExceptions.

In MessyExceptionHierarchy people have argued for a redesign of the JavaLanguage exception hierarchy. I agree with this, but first one has to take a broader view on this. The static hierarchy imposed by a single inheritance relation between the exception classes is asking for problems in the future.

Instead, I argue for DesignByInterface? when designing the exception system. I'm proposing something like the following:

All of these are interfaces.

               Throwable                CheckedException
                   |                          |
              ------------                    --------------------------------
              |          |                                                   |
          Exception    Error                                                 |
              |                                                              |
       ----------------------------------------------------------------------|
       |                          |                       |                 ||
 NullPointerException    ClassCastException    NumberFormatException?   IOException

We would then have a class called AbstractThrowable which provides the implementation of the methods that are today implemented in Throwable. CheckedException would be a tagging interface that can be put on any exception to make it checked.

Using this design one could easily create an exception that implements for example both IOException and RemoveException. It would also be possible to create a new exception that subclasses a non-checked exception and the CheckedException in order to created for example a CheckedNullPointerException (bad example, but you get my point).

-- EliasMartenson?


Excerpted from an interview with JamesGosling...

JDC: Why is Throwable not an interface? The name kind of suggests it should have been. Being able to catch for types, that is, something like try{}catch (<some interface or class>), instead of only classes. That would make [the] Java [programming language] much more flexible.

JamesGosling: The reason that the Throwable and the rest of those guys are not interfaces is because we decided, or I decided fairly early on. I decided that I wanted to have some state associated with every exception that gets thrown. And you can't do that with interfaces; you can only do that with classes. The state that's there is basically standard. There's a message, there's a snapshot, stuff like that — that's always there. and also, if you make Throwable an interface the temptation is to assign, to make any old object be a Throwable thing. It feels stylistically that throwing general objects is probably a bad idea, that the things you want to throw really ought to be things that are intended to be exceptions that really capture the nature of the exception and what went on. They're not just general data structures.


Ah, but maybe I didn't make myself completely clear. The state mentioned above would be contained in the abstract class AbstractThrowable. Any exception that can be thrown would have to extend from AbstractThrowable, either directly or indirectly. This would deal with both the problem of an exceptions state as well as prevent any class from becoming an exception. -- EliasMartenson?

If CheckedException is an interface which can tag a class at any point in the hierarchy - how is the compiler to know whether a particular method should check or not?

 interface FooException

class FooExceptionImpl extends AbstractException implements FooException, CheckedException ....

void breaksChecking() { Exception e = new FooExceptionImpl(...);

throw e; }
Admittedly a compiler could work this out but what if the call to new FooExceptionImpl was in another class which was plugged in at runtime - then you would completely lose checked exceptions. The reason that you can't circumvent checked exceptions in the JavaLanguage (unless you wrap them) is that Exception is checked - so you can cast checking onto an exception (e.g., (Exception)aRuntimeException) but not the other way.

-- PeterSumskas


CategoryException | CategoryJava


EditText of this page (last edited August 29, 2005) or FindPage with title or text search