Checked exceptions and Java Callables
Java supports checked exceptions. Many people have strong opinions about if they are good or bad. I believe they are good, but let's agree that Java has them and they're not going away.
(Any exception extending "Exception", which can to be thrown from a method, must be declared at the end of method's signature, and any caller of the method must handle the exception or itself declare to throw that type of exception; Any exception extending "RuntimeException" need not be declared on method signatures. A programmer is free to choose which superclass to extend when designing their own exceptions.)
There are two ways of dealing with tasks which should be run in the future, both of which are very inelegant w.r.t. checked exception handling.
- Runnable – the task (method) may not throw any checked exception, as the "run" method does not declare any checked exceptions (as "Runnable" defines the method; and the interface, provided by Java, cannot know what exceptions your code may throw)
- Callable – "Solves" the problem with Runnable in that the task/method may throw a checked exception. To achieve this the interface declares "throws Exception" meaning any checked exception may be thrown. This means the caller must handle "catch Exception" i.e. handle all checked exceptions, which again gives you no safety as to which exceptions can actually be thrown (the purpose of checked exceptions in the first place)
(In addition, the difference between these two interfaces is solely the way they deal with exceptions. But you wouldn't know that, or know which interface uses which strategy, by looking at their name!)
What one would need would be to extend the generics system to deal with exceptions. For example:
interface Callable<V,E> { V call() throws E; } class MyException extends Exception { .. } class MyCallable implements Callable<MyObject, MyException> { MyObject call() throws MyException { throw new MyException(); // ok to throw, signature declares it } } void usingCallable(MyCallable e) { e.call(); // error: must catch MyException }
The generic parameter "E" would have to be a list of exception classes as opposed to just one class.
Update: I was surprised to find out that using generic parameters for checked exceptions is basically supported! However it still isn't very useful, as:
- There is no way for the generic parameter E to be a list of exceptions
- Callable/Runnable interfaces provided by Java do not support it
- All the useful ThreadPool code that comes with Java support only Callable/Runnable