1

I am currently trying to program an event system using generic Listeners.
All listeners should be added to a single EventSource Object which will call their receiveEvent() methods for a specific event.

EventSource:

public class EventSource {

private HashMap<String, List<EventListener<? extends Event>>> events = new HashMap<>();

public synchronized <T extends Event> void fireEvent(T event){
    String key = event.getClass().getName();
    if(events.containsKey(key)){
        Iterator<EventListener<? extends Event>> i = events.get(key).iterator();
        while(i.hasNext()){
            i.next().receiveEvent(event); //Compiler Error
        }
    }
}

The resulting error is:

The method receiveEvent(capture#2-of ? extends Event) in the type EventListener is not applicable for the arguments (T)

EventListener is only:

public interface EventListener<T extends Event> {
    public void receiveEvent(T event);
}

Could someone explain what I am doing wrong, please?

1 Answer 1

1

The problem is that you're iterating over a List<EventListener<? extends Event>>, but the compiler doesn't know which class, Event or a subclass of Event, the ? wildcard could be. The T type parameter could also be Event or any subclass of Event. They do not match for this reason.

Try removing the wildcards:

// Removed wildcard
private HashMap<String, List<EventListener<Event>>> events = new HashMap<>();

public synchronized <T extends Event> void fireEvent(T event){
  String key = event.getClass().getName();
  if(events.containsKey(key)){
     // Removed wildcard.
     Iterator<EventListener<Event>> i = events.get(key).iterator();
     while(i.hasNext()){
        i.next().receiveEvent(event); // This compiles now.
     }
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you a lot that works. But I'm still not really getting why this doesn't work. When i am initializing a field of the type Class<? extends Event> with an object of the type Class<T extends Event> what actually works, wouldn't that have the same error?
Imagine 2 Event subclasses, Event1 and Event2. The T in theory could in reality be Event1 and the ? could be Event2, in which case they would be incompatible. The compiler's job with generics is to ensure type safety, and because of this possibility, it must disallow passing what could be an incompatible parameter to the method.
Okay, I think I kind of get it. Thanks a lot!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.