|
Quick Lists
|
|
Bug ID:
|
6364794
|
|
Votes
|
0
|
|
Synopsis
|
Callable/Future interfaces awkward w.r.t. checked exceptions
|
|
Category
|
java:classes_util_concurrent
|
|
Reported Against
|
|
|
Release Fixed
|
|
|
State
|
5-Cause Known,
request for enhancement
|
|
Priority:
|
4-Low
|
|
Related Bugs
|
|
|
Submit Date
|
19-DEC-2005
|
|
Description
|
The Callable and Future interfaces, and their usage in ExecutorService, are a bit awkward to use since they assume that the body of the code can throw arbitrary Exception (when that is usually not the case); when using a Future you have to pick apart the ExecutionException and deal with it somehow, maybe trying to cast it to various subtypes. This is not very pleasant.
I am attaching a runnable prototype (NetBeans project format, should run in 5.0 anyway) of enhanced interfaces that deal with checked exceptions more gracefully, by introducing a type parameter for an exception type. A quick summary for those who do not want to open the attachment:
public interface XCallable<V, E extends Exception> {
V call() throws E;
}
public interface XFuture<V, E extends Exception> {
V get() throws InterruptedException, E;
V get(long timeout, TimeUnit unit) throws InterruptedException, E, TimeoutException;
// etc.
}
Basic usage something like:
XFuture<String,IOException> f = executorService.submit(new XCallable<String,IOException>() {
public String call() throws IOException {
// ...
}
});
// ...
try {
String v = f.get();
} catch (IOException e) {
// ...
}
The working code should speak for itself as far as the details are concerned. Suggest that something like this could be made part of the j.u.concurrent.* APIs as a convenience, since it is not trivial to write your own (look at Bridge.java to see what I mean).
Some notes:
1. I found that using java.lang.Void was very handy as a type parameter for Callable/Future when you expect the body to return null. It forces the body to really return null (nothing else is assignable to this "type"), and the "Void" is visually reminiscent of the "void" you would use for a non-generified interface, so it is pretty clear to read - better Future<Void> than Future<?>, IMHO.
2. The type parameter for the enhanced interfaces can be RuntimeException if you do not except any checked exceptions to be thrown, and the compiler works as expected in this case (does not require anything to be caught, beyond the mandatory InterruptedException and if applicable TimeoutException).
3. If your body would throw more than one checked exception (e.g. IOException and SAXException for anything doing XML parsing), then the enhanced interfaces would not help you any (unless of course interfaces with multiple Exception type parameters were introduced). But I think this case is relatively uncommon.
4. Code in Bridge.java assumes that any Throwable caught will either be an Error or an Exception.
Posted Date : 2005-12-19 02:36:01.0
|
|
Work Around
|
N/A
|
|
Evaluation
|
Doug:
"We once discussed having Callable defined along the lines of the
suggestion in the RFE...
public interface XCallable<V, E extends Exception> {
V call() throws E;
}
But decided not to do it. Does anyone remember why?"
Joe:
>The Callable and Future interfaces, and their usage in ExecutorService,
>> are a bit awkward to use since they assume that the body of the code
>> can throw arbitrary Exception (when that is usually not the case)
But it *is* usually the case... (Or at least it's often not possible
to assume it's *not* the case.)
Josh:
"My guess is that the reason we didn't do it is that throws and generics don't mix well. The problem is that you have to declare the type that is thrown, which is frequently a disjunctive type, and Java provides now way of declaring such types. So you end up throwing the least common ancestor of all the exceptions that could be thrown, which is typically Exception, which is useless. "
Brian:
"Josh and I were discussing this recently and while neither of us
remembered why, I think it is because when a method throws one
exception, it might just as easily throw two, and there's no way to
express "throws IOException and SQLException" in a generic way."
Martin:
Looks like another Will Not Fix
Posted Date : 2006-02-04 01:52:13.0
Jesse:
It's true that you can only use the new interfaces if only one kind of
exception is thrown. My guess was simply that *most* bodies run would be
smallish and either throw no checked exceptions at all (my #2) or just
one kind of checked exception - i.e. that multiple checked exceptions
coalescing to j.l.Exception would be the less usual case. But this is
just a guess - someone with access to a large and diverse body of real
code using these interfaces would be better equipped to tell. My
experience is limited to using homegrown concurrency utilities in
NetBeans, where the great majority of such code blocks either throw
nothing or IOException, and where having to always catch and ignore
Exception would be unpleasant.
Doug:
I don't disagree that this would sometimes be useful. The trouble
is that you can't nicely have two forms of Callable etc everywhere,
and the way we have it is a bit more conservative, if sometimes more
annoying.
Jesse:
Yes, that is true. Might have been nicer to have Callable be XCallable
to begin with since XCallable<T,Exception> ~ Callable<T>. But no matter.
Posted Date : 2006-02-12 00:51:04.0
|
|
Comments
|
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|
|
|
 |