Java Generics: method X is not applicable for arguments

EventHandler.java:

public abstract class EventHandler<E extends EventArgs> { public abstract void HandleEvent(Object sender, E e); } 

Observers.java:

 public class Observers<E extends EventArgs> { private CopyOnWriteArrayList<EventHandler<? extends E>> mListeners = new CopyOnWriteArrayList<EventHandler<? extends E>>(); public void dispatchEvent(Object sender, E args) { if (mListeners != null) { for (EventHandler<? extends E> listener : mListeners) { listener.HandleEvent(sender, args); } } } } 

Next line:

 listener.HandleEvent(sender, args); 

Causes:

The HandleEvent (Object, capture # 3-of? Extends E) method in the EventHandler type is not applicable for arguments (object, E)

Can anyone fix this?

EDIT1 Reason ? super E ? super E does not work for me in that I have the following method inside the Observers class:

 public void addListener(EventHandler<? super E> listener) { mListeners.add(listener); } 

And this causes:

The add (EventHandler) method in type CopyOnWriteArrayList> is not applicable for arguments (EventHandler)

EDIT2

The reason the change is from ? super E ? super E to E does not work for me because of this: X is not applicable for Y arguments when X extends Y

This was already the case, but it did not work either :(

+6
source share
5 answers

Why do you declare mListeners equal to ~ ? extends E ? extends E , not just E ?

If you use

 private CopyOnWriteArrayList<EventHandler<E>> mListeners = new CopyOnWriteArrayList<EventHandler<E>>(); 

It will work.

Or take PECS (producer producer, consumer super). As others suggested

 private CopyOnWriteArrayList<EventHandler<? super E>> mListeners = new CopyOnWriteArrayList<EventHandler<? super E>>(); 

with corresponding changes to the for loop.

Edit: a more complete example. This does not show any warnings or errors, and, based on what you gave, will work.

 public static class Sandbox { public static interface EventArgs {} public static abstract class EventHandler<E extends EventArgs> { public abstract void HandleEvent(Object sender, E e); } public static class Observers<E extends EventArgs> { private CopyOnWriteArrayList<EventHandler<? super E>> mListeners = new CopyOnWriteArrayList<EventHandler<? super E>>(); public void dispatchEvent(Object sender, E args) { if (mListeners != null) { for (EventHandler<? super E> listener : mListeners) { listener.HandleEvent(sender, args); } } } public void addListener(EventHandler<? super E> listener) { mListeners.add(listener); } } } 
+3
source

Use ? super E ? super E instead ? extends E ? extends E

+2
source

Change

 for (EventHandler<? extends E> listener : mListeners) { 

to

 for (EventHandler<? super E> listener : mListeners) { 

The reason for this change is that the class has an instance of E However, if you have a listener expecting a subclass of class E , E does not guarantee the fulfillment of this contract. However, if the listener expects the base class E , then E guaranteed to satisfy the contract.

+1
source

What does EventHandler<? extends E> mean EventHandler<? extends E> EventHandler<? extends E> is an "event handler for E or some unknown subclass of E , therefore it potentially needs members of this unknown subclass, therefore it cannot be used with E

Probably all you need to do to fix this is to change the type of the list of event handlers to CopyOnWriteArrayList<EventHandler<E>> .

0
source

Change observer to:

 public static class Observers<E extends EventArgs> { private CopyOnWriteArrayList<EventHandler<E>> mListeners = new CopyOnWriteArrayList<EventHandler<E>>(); public void dispatchEvent(Object sender, E args) { if (mListeners != null) { for (EventHandler<E> listener : mListeners) { listener.HandleEvent(sender, args); } } } } 

E is already defined in the class definition as an extension of EventArgs; it does not need to be redefined with each subsequent use.

0
source

Source: https://habr.com/ru/post/901508/


All Articles