Exception transparency

Brian Goetz brian.goetz at oracle.com
Mon Sep 24 08:39:48 PDT 2012


The purpose of exception transparency is not simply to be able to 
declare "SAM with Exception", but for methods to be generic in their 
thrown methods.  The canonical example is:

   <throws X> forEach(Block<T, throws X> block) throws X;

So that the compiler can say "whatever the block throws, must also be 
thrown by the forEach call."  Then, when the user says

   forEach(x -> { throw new FooException(); }

we know that the forEach call can be treated as throwing FooException. 
That's where the transparency is -- that forEach is transparent to the 
exceptions thrown by lambdas passed to it.  Whether the SAMs are 
"transparent" -- which is what the alternate proposal offers -- does not 
really solve the key problem.

BGGA exception transparency would give us this, but at too high a cost. 
  I don't see your proposed model giving us this, because it doesn't 
allow a "Callable throws FooException" to be passed to forEach.


On 9/24/2012 11:27 AM, Ali Lahijani wrote:
> Brian,
>
> It might be too soon for a comment from the public, I know the EG is
> not yet done with exception transparency.
> Anyway, I hope it is not inappropriate.
>
> I currently know of two options for exception transparency. Besides
> BGGA-style throws type parameters, there are full blown union types.
> But both need changing existing SAM interface definitions to add new
> type parameters for the list of exceptions, which has several
> drawbacks.
>
> I was thinking if Java could add throws clauses to existing SAM types,
> without the SAM type itself being required to declare anything.
> Something like Callable<X> throws E1, E2. The definition of Callable
> will not be changed and the throws clause here effectively overrides
> the original one at Callable.run().
>
>      Callable<X> throws CheckedFooException c = () -> { throw new
> CheckedFooException() };
>
> or maybe:
>      Callable<X> c throws CheckedFooException = () -> { throw new
> CheckedFooException() };
>
> I cannot think of a legitimate reason why a SAM type's definition
> might want to categorically prohibit exception transparency. So,
> requiring them to state the obvious, that transparency is allowed,
> seems redundant.
>
> There is a simple rule of subtyping which the compiler enforces.
> Callable<X> throws E_i is assignable from Callable<X> throws E_j iff
> any single E_j extends some E_i. There is no cast operator in the
> other direction. If you want that, you have to wrap the expression in
> a try-catch.
>
> So in particular, Runnable will not be assignable from Runnable throws
> Foo, (if the latter is indeed permitted).
>
> A light weight erasure-based approach is to keep just one Class object
> for Callable. Additional throws clauses are implemented as an
> attribute on types at declaration sites. Possibly even a jsr308 type
> annotation like @Throws(CheckedFooException.class) or  @Throws("E1",
> "E2") can do. Other possibilities also come to mind here.
>
> Best
>


More information about the lambda-spec-observers mailing list