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