It is designed in Java that I get a Throwable object if I invoke getCause() on an Exception.
I understand that getCause() is simply inherited from Throwable and I know that Throwable can be either an Error or an Exception, but a programmer generally should work only on the Exception level without dealing with Throwable/Error classes.
What was the reason in the Java exception hierarchy design to, for example, not include getCause() in the Exception class that would return an Exception object?
Here is an illustration of the inconvenience taken from Java Concurrency In Practice (Brian Goetz):
public class Preloader {
private final FutureTask<ProductInfo> future =
new FutureTask<ProductInfo>(new Callable<ProductInfo>() {
public ProductInfo call() throws DataLoadException {
return loadProductInfo();
}
});
private final Thread thread = new Thread(future);
public void start() { thread.start(); }
public ProductInfo get()
throws DataLoadException, InterruptedException {
try {
return future.get();
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof DataLoadException)
throw (DataLoadException) cause;
else
throw launderThrowable(cause);
}
}
}
It is said in the book:
...but also because the cause of the
ExecutionExceptionis returned as aThrowable, which is inconvenient to deal with...
And in launderThrowable() it is dealt with rethrowing Error right away (because we don't want to deal with it) and returning RuntimeException:
public static RuntimeException launderThrowable(Throwable t) {
if (t instanceof RuntimeException)
return (RuntimeException) t;
else if (t instanceof Error)
throw (Error) t;
else
throw new IllegalStateException("Not unchecked", t);
}