I am writing an event system for my Java application and I keep getting confused about generics.
Let's say this is EventManager.java:
public class EventManager {
    private final Map<Class<? extends Event>, List<EventHandler<?>>> eventHandlerMap = new HashMap<>();
    public synchronized <T extends Event> void fire(T event) {
        Class<? extends Event> eventClass = event.getClass();
        if (!eventHandlerMap.containsKey(eventClass)) return;
        List<EventHandler<? extends Event>> handlerList =
                eventHandlerMap.get(eventClass);
        for (EventHandler<? extends Event> eventHandler : handlerList) {
            eventHandler.handleEvent(event.getClass().cast(event));
        }
    }
}
Event.java:
public abstract class Event {
}
and EventHandler.java:
public abstract class EventHandler<T extends Event> {
    public abstract void handleEvent(T event);
}
IntelliJ IDEA reports me the following error:
As a temporary mitigation I have added the following method to EventHandler class:
@SuppressWarnings("unchecked")
public final void handleEvent0(Event event) {
    handleEvent((T) event);
}
...and changed the fire method in EventManager:
public synchronized void fire(Event event) {
    Class<? extends Event> eventClass = event.getClass();
    if (!eventHandlerMap.containsKey(eventClass)) return;
    List<EventHandler<? extends Event>> handlerList =
            eventHandlerMap.get(eventClass);
    for (EventHandler<? extends Event> eventHandler : handlerList) {
        eventHandler.handleEvent0(event);
    }
}
This does work however I am wondering what I have done wrong initially and how can I properly fix it. Please help and sorry for my English!
 
    