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() 

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