简体   繁体   中英

Java Generics: Method X is not applicable for the 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);
            }
        }
    }
}

The following line:

listener.HandleEvent(sender, args);

Causes:

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

Does anybody how to fix this?

EDIT1 The reason ? super E ? super E doesn't work for me is that I have the following method inside Observers class:

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

And that causes:

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

EDIT2

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

It was already like that but that didn't work neither :(

Why are you declaring mListeners to be ~ ? extends E ? extends E rather than just E ?

If you use

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

It'll work.

Or adopt PECS (Producer Extends, Consumer Super). As others have suggested

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

with related changes to the for loop.

Edit: A fuller example. This shows no warnings or errors, and, based on what you've given, would 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);
        }        
    }
}

Use ? super E ? super E instead of ? extends E ? extends E .

Change

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

to

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

The reason this change is required is that the class has an instance of E . However, if you have a listener that expects a sub-class of E , E is not guaranteed to satisfy this contract. However, if the listener expects a base-class of E , then E is guaranteed to satisfy the contract.

What EventHandler<? extends E> EventHandler<? extends E> means is "an event handler for E or some unknown subclass of E , so it potentially needs members of that unknown subclass, so it cannot be used with an E .

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

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 has already been defined in the class definition as extending EventArgs, it doesn't need to get redefined in each subsequent use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM