Invalid method reference with generics

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Jun 26 10:27:18 PDT 2013


On 26/06/13 18:13, Nick Williams wrote:
> That compiles and runs (I just tested it), but the two uses of register are completely opposite. Register with the anonymous inner class works as I expect: I can pass in an ApplicationListener whose type_extends_  ApplicationEvent. Register with the method reference is opposite: I can pass in an ApplicationListener whose type_is extended by_  ApplicationEvent. I am very convinced that that's wrong. In fact, my IDE highlights the anonymous inner class as a warning that says "Anonymous ApplicationListener<Event1>" can be replaced with lambda," but when I let it replace it I get incompatible parameter types upon compilation.
I think the fact that the IDE suggests that a lambda might be use is a 
bug in the lambda detector; a lambda cannot be used as, a lambda 
parameter type must be identical to that of the descriptor itr will be 
passed to. Subtyping is only allowed for method references, but the 
other way around, not the one you are asking for.

Example:

interface I {
    void m(Number n)
}

void g1(Object o)
void g2(Number n)
void g3(Integer i)

void m(I i);

m(this::g1); //ok, Number subtype of Object
m(this::g2); //ok, Number subtype of Number
m(this::g3); //error, Number not a subtype of Integer

Note that this semantics is quite standard, as parameter types in 
function types are treated in a contravariant fashion (i.e. the function 
type accepting a more constrained domain is more general - this comes 
from Liskov - a subtype of a function type cannot start arbitrarily 
rejecting input values that were accepted by a super type).

Maurizio


More information about the lambda-dev mailing list