gpt4 book ai didi

java - 泛型映射 : read and write

转载 作者:行者123 更新时间:2023-12-01 21:17:39 26 4
gpt4 key购买 nike

有许多不同的事件,它们都实现相同的接口(interface):

interface Event {}
class FooEvent implements Event {}
class BarEvent implements Event {}

每个事件都有一个专用的处理程序:

interface EventHandler<T extends Event> {
void handle(T event);
}
class FooEventHandler implements EventHandler<FooEvent> {
@Override
public void handle(FooEvent event) { }
}
class BarEventHandler implements EventHandler<BarEvent> {
@Override
public void handle(BarEvent event) { }
}

所有事件处理程序均创建一次并添加到 map 中。每当事件发生时,应该使用此映射来查找正确的事件处理程序。

class Main {
Map<Class<? extends Event>, EventHandler<? extends Event>> eventHandlerRegistry = Map.of(
FooEvent.class, new FooEventHandler(),
BarEvent.class, new BarEventHandler()
);

void handleEvent(Event event) {
EventHandler<? extends Event> handler = this.eventHandlerRegistry.get(event.getClass());
handler.handle(event); // DOES NOT COMPILE: needed=capture<? extends Event>, given=Event
}
}

不幸的是,最后一行无法编译。我可以通过省略 EventHandler 的类型参数来编译它,如下所示:

EventHandlerhandler = this.eventHandlerRegistry.get(event.getClass());
handler.handle(event); // WARNING: unchecked call to 'handle(T)' as a member of raw type 'EventHandler'

但这感觉不太对劲......我知道PECS ,但我感觉有点被困住了,因为我生成并消耗了我的事件处理程序。

我怎样才能干净地实现这个?

最佳答案

如果您要在同一个映射中混合使用(通用)处理程序,则无法实现类型安全。据我所知,使代码类型安全的方法是摆脱 EventHandler 上的泛型类型参数;但这是您要避免的一件事。

如果您可能会牺牲类型安全性,并且知道您的处理程序将始终与指定的类匹配,那么您可以尝试以下操作:

private <T extends Event> EventHandler<T> getHandler(Class<?> eventClass) {
return (EventHandler<T>)
this.eventHandlerRegistry.get(eventClass); //Unchecked cast
}

然后使您的 handleEvent 方法通用:

<T extends Event> void handleEvent(T event) {
EventHandler<T> handler = this.getHandler(event.getClass());
handler.handle(event);
}

此方法将成功编译,且不会发出警告。您唯一需要确保的是 eventHandlerRegistry 永远不会被以下内容污染:

put(FooEvent.class, new BarEventHandler())); //this can happen

关于java - 泛型映射 : read and write,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59322517/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com