Java 带有映射的EventSource<;类别<;?扩展事件>;,列表<;EventListener<;?扩展事件>&燃气轮机;没有未经检查的呼叫

Java 带有映射的EventSource<;类别<;?扩展事件>;,列表<;EventListener<;?扩展事件>&燃气轮机;没有未经检查的呼叫,java,generics,observer-pattern,unchecked,Java,Generics,Observer Pattern,Unchecked,我需要使用每个事件类的侦听器列表来实现观察者模式 我有: 空接口事件 public interface Event {} 侦听器接口: public interface EventListener<T extends Event> { void handle(T event); Class<T> getEventClass();} 公共接口事件监听器{ 无效句柄(T事件); 类getEventClass();} 和事件来源: public class EventS

我需要使用每个事件类的侦听器列表来实现观察者模式

我有:

空接口事件

public interface Event {}
侦听器接口:

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

Class<T> getEventClass();}
公共接口事件监听器{
无效句柄(T事件);
类getEventClass();}
和事件来源:

public class EventSource {
private final Map<Class<? extends Event>, List<EventListener<? extends Event>>> listeners = new HashMap<>();

public <T> void subscribe(EventListener<? extends Event> listener) {
    Class<? extends Event> eventClass = listener.getEventClass();
    if (!listeners.containsKey(eventClass)) {
        listeners.put(eventClass, new ArrayList<>());
    }
    listeners.get(eventClass).add(listener);
}

public void unsubscribe(EventListener listener) {
    listeners.remove(listener.getEventClass());
}

public void fire(Event event) {
    for (EventListener listener : listeners.get(event.getClass())) {
        listener.handle(event); //<-- Unchecked call to 'handle(T)' as a member of raw type...
    }
}}
公共类事件源{
私人最终地图改变

listeners.put(eventClass,newarraylist());

listeners.put(eventClass,newarraylist未检查的调用)报告警告是有充分理由的-您使用了原始形式的
EventListener
。当您提供类型参数
?extensed Event
,它给出了编译错误,因为编译器不知道
Event
EventListener
处理哪个
Event
类型-它只知道它是
Event
的特定类型kewise,它不知道
事件的运行时类型
——它可以是任何特定类型的
事件

必须知道类型才能使其有意义。我将使
EventSource
成为泛型,使用有界泛型类型参数指定
Event
的类型

class EventSource<E extends Event> {
还有许多其他声明将更改为使用
E

现在,
fire
将接受一个
E
,以便它可以被传递到
句柄

public void fire(E event) {
   for (EventListener<E> listener : listeners.get(event.getClass())) {
      listener.handle(event); // Now this compiles
   }
}
公共空间火灾(E事件){
for(EventListener:listeners.get(event.getClass())){
handle(event);//现在编译
}
}

使用NetBeans 7.4我不知道您的错误,但我确实知道:
不兼容类型:ArrayList无法转换为ListThank谢谢您的建议。我理解这个问题。在MapThank中,我不能简单地更改Thank,但它不会更改任何内容。在Java 7(diamond)中是自动替代吗EventListener@VitalyChibrikov我使用的是Java 7,并且没有在LHS运算符上定义菱形运算符,因为您只是使用
put
调用创建ArrayList。因此,必须显式设置它,否则编译器只会推断是的,您是对的。listeners.put(eventClass,new ArrayList());是1.8项目级别,而不是1.7。正如您所提到的,在Java 7中,我需要通用初始化的完整版本。
listeners.put(eventClass, new ArrayList<EventListener<? extends Event>>());        
class EventSource<E extends Event> {
private final Map<Class<? extends Event>, List<EventListener<E>>> listeners = new HashMap<>();
public void fire(E event) {
   for (EventListener<E> listener : listeners.get(event.getClass())) {
      listener.handle(event); // Now this compiles
   }
}