带有Map<Class<? extends Event>、List<EventListener<? extends Event>>的EventSource,没有未经检查的调用

问题描述 投票:0回答:2

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

我有:

空界面事件

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

但在这种情况下,我有“句柄无法应用于...”编译错误。

提前致谢!

java generics observer-pattern unchecked
2个回答
1
投票

报告“未经检查的呼叫”警告是有充分理由的 - 您使用了

EventListener
的原始形式。当您给出类型参数
? extends Event
时,它会给出编译错误,因为编译器不知道
Event
处理哪个
EventListener
- 它只知道它是
Event
的特定类型。同样,它不知道
event
的运行时类型 - 它可能是
Event
的任何特定类型。

必须知道类型才能有意义。我会将

EventSource
设为泛型,用有界泛型类型参数指定
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
投票

改变

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

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

我相信这将使接口方法

handle
表现得像预期的那样

© www.soinside.com 2019 - 2024. All rights reserved.