When an exception is thrown by a method that is executing under several layers?

I know this is an old question but I've spent a while wrestling with checked exceptions and I've something to add. Please forgive me for the length of it!

My main beef with checked exceptions is that they ruin polymorphism. It's impossible to make them play nicely with polymorphic interfaces.

Take the good ol' Java List interface. We have common in-memory implementations like ArrayList and LinkedList. We also have the the skeletal class AbstractList which makes it easy to design new types of list. For a read-only list we need to implement only two methods: size() and get(int index).

This example WidgetList class reads some fixed-size objects of type Widget (not shown) from a file:

class WidgetList extends AbstractList<Widget> {
    private static final int SIZE_OF_WIDGET = 100;
    private final RandomAccessFile file;

    public WidgetList(RandomAccessFile file) {
        this.file = file;
    }

    @Override
    public int size() {
        return (int)(file.length() / SIZE_OF_WIDGET);
    }

    @Override
    public Widget get(int index) {
        file.seek((long)index * SIZE_OF_WIDGET);
        byte[] data = new byte[SIZE_OF_WIDGET];
        file.read(data);
        return new Widget(data);
    }
}

By exposing the Widgets using the familiar List interface, you can retrieve items (list.get(123)) or iterate a list (for (Widget w : list) ...) without needing to know about WidgetList itself. One can pass this list to any standard methods that use generic lists, or wrap it in a Collections.synchronizedList. Code that uses it need neither know nor care whether the "Widgets" are made up on the spot, come from an array, or are read from a file, or a database, or from across the network, or from a future subspace relay. It will still work correctly because the List interface is correctly implemented.

Except it isn't. The above class doesn't compile because the file access methods may throw an IOException, a checked exception which you have to "catch or specify". You can't specify it as thrown -- the compiler won't let you because that would violate the contract of the List interface. And there is no useful way that WidgetList itself can handle the exception (as I'll expound on later).

Apparently the only thing to do is catch and rethrow checked exceptions as some unchecked exception:

@Override
public int size() {
    try {
        return (int)(file.length() / SIZE_OF_WIDGET);
    } catch (IOException e) {
        throw new WidgetListException(e);
    }
}

public static class WidgetListException extends RuntimeException {
    public WidgetListException(Throwable cause) {
        super(cause);
    }
}

((Edit: Java 8 has added an UncheckedIOException class for exactly this case: for catching and rethrowing IOExceptions across polymorphic method boundaries. Kind of proves my point!))

So checked exceptions simply don't work in cases like this. You can't throw them. Ditto for a clever Map backed by a database, or an implementation of java.util.Random connected to a quantum entropy source via a COM port. As soon as you try to do anything novel with the implementation of a polymorphic interface, the concept of checked exceptions fails. But checked exceptions are so insidious that they still won't leave you in peace, because you still have to catch and rethrow any from lower-level methods, cluttering the code and cluttering the stack trace.

I find that the ubiquitous Runnable interface is often backed into this corner, if it calls something which throws checked exceptions. It can't throw the exception as is, so all it can do is clutter the code by catching and rethrowing as a RuntimeException.

Actually, you can throw undeclared checked exceptions if you resort to hacks. The JVM, at run time, doesn't care about checked exception rules, so we need to fool only the compiler. The easiest way to do this is to abuse generics. This is my method for it (class name shown because (before Java 8) it's required in the calling syntax for the generic method):

class Util {
    /**
     * Throws any {@link Throwable} without needing to declare it in the
     * method's {@code throws} clause.
     * 
     * <p>When calling, it is suggested to prepend this method by the
     * {@code throw} keyword. This tells the compiler about the control flow,
     * about reachable and unreachable code. (For example, you don't need to
     * specify a method return value when throwing an exception.) To support
     * this, this method has a return type of {@link RuntimeException},
     * although it never returns anything.
     * 
     * @param t the {@code Throwable} to throw
     * @return nothing; this method never returns normally
     * @throws Throwable that was provided to the method
     * @throws NullPointerException if {@code t} is {@code null}
     */
    public static RuntimeException sneakyThrow(Throwable t) {
        return Util.<RuntimeException>sneakyThrow1(t);
    }

    @SuppressWarnings("unchecked")
    private static <T extends Throwable> RuntimeException sneakyThrow1(
            Throwable t) throws T {
        throw (T)t;
    }
}

Hurray! Using this we can throw a checked exception any depth up the stack without declaring it, without wrapping it in a RuntimeException, and without cluttering the stack trace! Using the "WidgetList" example again:

@Override
public int size() {
    try {
        return (int)(file.length() / SIZE_OF_WIDGET);
    } catch (IOException e) {
        throw sneakyThrow(e);
    }
}

Unfortunately, the final insult of checked exceptions is that the compiler refuses to allow you to catch a checked exception if, in its flawed opinion, it could not have been thrown. (Unchecked exceptions do not have this rule.) To catch the sneakily thrown exception we have to do this:

try {
    ...
} catch (Throwable t) { // catch everything
    if (t instanceof IOException) {
        // handle it
        ...
    } else {
        // didn't want to catch this one; let it go
        throw t;
    }
}

That is a bit awkward, but on the plus side, it is still slightly simpler than the code for extracting a checked exception that was wrapped in a RuntimeException.

Happily, the throw t; statement is legal here, even though the type of t is checked, thanks to a rule added in Java 7 about rethrowing caught exceptions.


When checked exceptions meet polymorphism, the opposite case is also a problem: when a method is spec'd as potentially throwing a checked exception, but an overridden implementation doesn't. For example, the abstract class OutputStream's write methods all specify throws IOException. ByteArrayOutputStream is a subclass that writes to an in-memory array instead of a true I/O source. Its overridden write methods cannot cause IOExceptions, so they have no throws clause, and you can call them without worrying about the catch-or-specify requirement.

Except not always. Suppose that Widget has a method for saving it out to a stream:

public void writeTo(OutputStream out) throws IOException;

Declaring this method to accept a plain OutputStream is the right thing to do, so it can be used polymorphically with all kinds of outputs: files, databases, the network, and so on. And in-memory arrays. With an in-memory array, however, there is a spurious requirement to handle an exception that can't actually happen:

ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
    someWidget.writeTo(out);
} catch (IOException e) {
    // can't happen (although we shouldn't ignore it if it does)
    throw new RuntimeException(e);
}

As usual, checked exceptions get in the way. If your variables are declared as a base type that has more open-ended exception requirements, you have to add handlers for those exceptions even if you know they won't occur in your application.

But wait, checked exceptions are actually so annoying, that they won't even let you do the reverse! Imagine you currently catch any IOException thrown by write calls on an OutputStream, but you want to change the variable's declared type to a ByteArrayOutputStream, the compiler will berate you for trying to catch a checked exception that it says cannot be thrown.

That rule causes some absurd problems. For example, one of the three write methods of OutputStream is not overridden by ByteArrayOutputStream. Specifically, write(byte[] data) is a convenience method that writes the full array by calling write(byte[] data, int offset, int length) with an offset of 0 and the length of the array. ByteArrayOutputStream overrides the three-argument method but inherits the one-argument convenience method as-is. The inherited method does exactly the right thing, but it includes an unwanted throws clause. That was perhaps an oversight in the design of ByteArrayOutputStream, but they can never fix it because it would break source compatibility with any code that does catch the exception -- the exception that has never, is never, and never will be thrown!

That rule is annoying during editing and debugging too. E.g., sometimes I'll comment out a method call temporarily, and if it could have thrown a checked exception, the compiler will now complain about the existence of the local try and catch blocks. So I have to comment those out too, and now when editing the code within, the IDE will indent to the wrong level because the { and } are commented out. Gah! It's a small complaint but it seems like the only thing checked exceptions ever do is cause trouble.


I'm nearly done. My final frustration with checked exceptions is that at most call sites, there's nothing useful you can do with them. Ideally when something goes wrong we'd have a competent application-specific handler that can inform the user of the problem and/or end or retry the operation as appropriate. Only a handler high up the stack can do this because it's the only one that knows the overall goal.

Instead we get the following idiom, which is rampant as a way to shut the compiler up:

try {
    ...
} catch (SomeStupidExceptionOmgWhoCares e) {
    e.printStackTrace();
}

In a GUI or automated program the printed message won't be seen. Worse, it plows on with the rest of the code after the exception. Is the exception not actually an error? Then don't print it. Otherwise, something else is going to blow up in a moment, by which time the original exception object will be gone. This idiom is no better than BASIC's On Error Resume Next or PHP's error_reporting(0);.

Calling some kind of logger class is not much better:

try {
    ...
} catch (SomethingWeird e) {
    logger.log(e);
}

That is just as lazy as e.printStackTrace(); and still plows on with code in an indeterminate state. Plus, the choice of a particular logging system or other handler is application-specific, so this hurts code reuse.

But wait! There is an easy and universal way to find the application-specific handler. It's higher up the call stack (or it is set as the Thread's uncaught exception handler). So in most places, all you need to do is throw the exception higher up the stack. E.g., throw e;. Checked exceptions just get in the way.

I'm sure checked exceptions sounded like a good idea when the language was designed, but in practice I've found them to be all bother and no benefit.

When you write a method that throws a checked exception you must?

If a method declares a checked exception (i.e., an exception other than Error or RuntimeException), you must invoke it in a try-catch block or declare to throw the exception in the calling method.

What happens when an exception is thrown but the try statement does not have a catch clause that is capable of catching it?

What happens when an exception is thrown, but the try statement does not have a catch clause that is capable of catching it? Control of the program is passed to the previous method in the call stack. If that method cannot handle the exception, then control is passed again, up the call stack, to the previous method.

When the code in a try block may throw more than one type of exception you need to write a catch?

When the code in a try block may throw more than one type of exception, you need to write a catch clause for each type of exception that could potentially be thrown. All of the exceptions that you will handle are instances of classes that extend this class.
When catching multiple exceptions that are related to one another through inheritance, you should handle the more specialized exception classes before the more general exception classes. To serialize an object and write it to the file, use this method of the ObjectOutputStream class.