Exception transparency

Alex Buckley alex.buckley at oracle.com
Thu Jun 10 14:14:32 PDT 2010


On 6/9/2010 1:23 AM, Maurizio Cimadamore wrote:
> On 09/06/10 00:44, Neal Gafter wrote:
>> >  Function<throws IOException>  e = #(IOException e){...};
> Hi
> just to be clear, on which basis would you reject the above statement? I 
> guess your argument is that a lambda accepting an argument  of type E 
> cannot be SAM-converted to an interface whose method accepts an argument 
> of type 'throws E' (and, more generally, that E and 'throws E' are not 
> interchangeable). Am I reading correctly?

Neal points out that exception type arguments are not covariant:

interface Function<throws E> { void m(Function<throws E> fe) throws E; }

Function<throws IOException> e = #(Function<throws IOException> x){};
Function<throws Exception>   f = e;  // Assume this is OK

Function<throws SAXException> g = #(Function<throws SAXException> x){};
try {
   f.m(g);
   // f.m statically expects a Function<throws Exception>,
   // so an actual param of Function<throws SAXException> is OK.
   // Or is it? f.m really expects a Function<throws IOException>.
catch (Exception ex) {}

Nathan Bryant pointed this out too, albeit rather tersely. We had hoped 
to ban exception type parameters in many locations, such as a bare E for 
a method's formal parameter type, while allowing them in other 
locations, notably as exception type arguments _in_ formal parameter 
types. But _any_ appearance in a contravariant context is no good.

Also, as Nathan said, exception type arguments are not contravariant either:

Function<throws Exception> e =
   #(Function<throws Exception> x){ throw new SAXException(); };
Function<throws IOException> f = e;  // Clearly unsafe

(And even if it was OK, contravariant exception type arguments couldn't 
appear in any covariant context, such as a return type, and thus their 
utility would be restricted, dual to Neal's comment.)

Alex


More information about the lambda-dev mailing list