2015-01-07 12 views
2

我需要实现观察者模式与每个事件类的监听器列表。带有Map <Class <?的EventSource?扩展Event>,List <EventListener <?扩展事件>>没有未经检查的呼叫

我:

空接口事件

public interface Event {} 

听众接口:

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

Class<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... 
    } 
}} 

它的工作原理,但我有“未经检查的呼叫“ 警告。如何避免它?

我想:

public void fire(Event event) { 
    for (EventListener<? extends Event> listener : listeners.get(event.getClass())) { 
     listener.handle(event);//<-- compilation error 
    } 
} 

但在这种情况下,我有“手柄不能适用于......”编译错误。

在此先感谢!

+0

使用NetBeans 7.4我没有得到你的错误,但我得到:'不兼容的类型:ArrayList的不能转换列出());扩展事件>>'' – gtgaxiola

+0

感谢您的建议。我理解这个问题。在Map ,List >>编译器不知道“?”在课堂上和“?”在列表中是相同的类型。我看不到如何告诉编译器。 – Vitaly

回答

1

报道了一个很好的理由的“取消选中电话”警告 - 您使用的是原始格式EventListener。当你给出类型参数? extends Event时,它给出了编译错误,因为编译器没有处理哪个Event - 它只知道它是特定类型的Event。同样,它不知道event的运行时类型 - 它可以是任何特定类型的Event

该类型必须为此有意义。我会制作EventSource generic,指定具有有界泛型类型参数的Event的类型。

class EventSource<E extends Event> { 

许多? extends Event声明将改变使用E,例如

private final Map<Class<? extends Event>, List<EventListener<E>>> listeners = new HashMap<>(); 

还有很多其他声明会改为使用E。现在

fire将采取E,以便它可以被传递给handle

public void fire(E event) { 
    for (EventListener<E> listener : listeners.get(event.getClass())) { 
     listener.handle(event); // Now this compiles 
    } 
} 
+0

谢谢,但我不能简单地改变<?将Event>扩展为,在这种情况下,我无法为EventListener的子类调用subscribe()。 – Vitaly

0

变化

listeners.put(eventClass, new ArrayList<>());    

listeners.put(eventClass, new ArrayList<EventListener<? extends Event>>());   

我相信,这将使接口方法handle表现为应该

+0

谢谢,但它没有改变。在Java 7 <>(菱形)中是EventListener <?扩展事件> – Vitaly

+0

@VitalyChibrikov我正在使用Java 7,并且<>菱形运算符未在LHS运算符上定义,因为您只是使用'put'调用创建ArrayList。因此你必须明确地设置它,否则编译器只会推断是 gtgaxiola

+0

是的,你是对的。 listeners.put(eventClass,new ArrayList <>());是1.8项目级别,而不是1.7。正如你所提到的,在Java 7中,我需要完整版本的通用初始化。 – Vitaly

相关问题