Exception transparency
Brian Goetz
brian.goetz at oracle.com
Thu Sep 20 15:03:06 PDT 2012
At the in-person meeting, I promised a writeup of why BGGA-style
exception transparency seemed a poor balance of complexity/benefit for
Java SE 8.
Basically, this proposal would extend generics with variadic type
arguments (where a generic type argument can represent a list of zero or
more types.) This would let us define SAM types that abstract over the
set of types thrown from their method:
interface Block<T, throws X> {
void apply(T arg) throws X;
}
The "throws X" would indicate that X is a variadic type argument.
Similarly, we could define generic methods that are generic in X:
interface List<T> {
<throws X> void forEach(Block<T, X> block) throws X;
}
This seems kind of attractive at first. But, this gets uglier when you
try to write even a simple combinator method, such as Predicate.and:
class Predicates {
static<T, throws E1, throws E2>
Predicate<T, E1|E2> and(Predicate<? super T, E1> p1,
Predicate<? super T, E2> p2) {
return t -> p1.apply(t) && p2.apply(t);
}
}
It's possible, but its pretty ugly, really easy to get wrong, and (like
everything else with generics) if the library writer gets it wrong, the
user is hosed. The generics foo overwhelms the simple body of the and()
method.
We've done a lot more investigation, but here is just a quick summary of
disadvantages of BGGA-style exception transparency:
- Makes the declarations of functional interfaces and lambda-consuming
methods more complicated
- Doubly so for combinator methods (e.g., Predicates.and)
- Requires extra args at the use site on the non-throwing case (e.g.,
Predicate<String, Void>), which is ugly and “leaky” (though this could
probably be patched up in common cases, at the cost of extra complexity)
- Challenges for retrofitting existing functional interfaces (e.g.,
Runnable, Comparator) because most existing SAM types are not generic
over exceptions
- Takes liberties with meaning of generic type params – sometimes they
refer to types, sometimes to sets of types
- Inference undecidability – if you have a generic method that accepts
a SAM type throwing both X1, X2, cannot partition the set of exceptions
thrown by the lambda body
- Unsoundness of “catch X” – X will be erased, and you would be
catching Exception instead
- Would likely interact with future attempts to extend generics, such
as varargs generics, which would be desirable for things like tuples
- Not very transparent at all -- pretty intrusive, in fact.
We're continuing to explore some ideas that might make exception
transparency more tractable, but these would definitely be out of scope
for Java SE 8.
More information about the lambda-spec-experts
mailing list