Invalid method reference with generics

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Jun 26 09:33:52 PDT 2013


Hi Nick,
method reference applicability is defined in a way so that the parameter 
types inferred from the target (ApplicationEvent in your case) should be 
compatible with the argument types in the method reference signature 
(Event1/Event2 in your case). Since ApplicationEvent is _not_ a subtype 
of Event1/Event2 (it's the other way around), the method reference is 
not compatible with that target.

Maurizio

On 23/06/13 18:59, Nick Williams wrote:
> Given this interface:
>
> public interface ApplicationListener<E extends ApplicationEvent>  extends EventListener {
>     void onApplicationEvent(E e);
> }
>
> And these two events:
>
> public class Event2 extends ApplicationEvent {
>     public Event1(Object source) {
>         super(source);
>     }
> }
>
> public class Event2 extends ApplicationEvent {
>     public Event2(Object source) {
>         super(source);
>     }
> }
>
> And this class:
>
> public class MyBean {
>     public void onEvent1(Event1 event1) { }
>
>     public void onEvent2(Event2 event2) { }
>
>     public void initialize() {
>         register(this::onEvent2);
>     }
>
>     public static void register(ApplicationListener<? extends ApplicationEvent> listener) { }
>     // I've also tried public static void register(ApplicationListener<ApplicationEvent> listener) { }
>     // I've also tried public static void register(ApplicationListener<?> listener) { }
>     // I've also tried public static void register(ApplicationListener listener) { }
> }
>
> Can someone tell my why this fails to compile with the following error?
>
> Error: java: incompatible types: invalid method reference
>     incompatible types: x.x.x.ApplicationEvent cannot be converted to x.x.x.Event2
>
> This seems like quite the limitation. Why can't the compiler match onEvent2 to the method in ApplicationEvent?
>
> If I change onEvent2's signature to take an ApplicationEvent instead of an Event2, it compiles fine. If I change register's signature to take an ApplicationListener<Event2> instead of an ApplicationListener<? extends ApplicationEvent>, it also compiles fine. Is there some other way to do what I want to do here?
>
> Note: I also tried public static <E extends ApplicationEvent> void register(ApplicationListener<E> listener) { }, but that resulted in a different error, "Error: java: incompatible types: Cannot instantiate inference variables E because of an inference loop."
>
> Nick
>



More information about the lambda-dev mailing list