gpt4 book ai didi

java - 如何在 java 中为事件监听器模式创建并触发 Consumers 集合

转载 作者:行者123 更新时间:2023-11-30 08:17:15 26 4
gpt4 key购买 nike

我正在尝试创建一个非常标准的事件监听器/广播系统。现在只是尝试不同的想法,看看它们在我们的领域如何运作。

我遇到的问题是我似乎无法找到使用泛型实际调用 Consumer 的正确语法。

private ConcurrentHashMap<Class<? extends Event>, ConcurrentLinkedQueue<Consumer<? extends Event>>> listeners;

public <T extends Event> void listen(Consumer<T> consumer, Class<T> clazz){
ConcurrentLinkedQueue<Consumer<? extends Event>> consumers = listeners.get(clazz);
if (consumers == null) {
consumers = new ConcurrentLinkedQueue<>();
listeners.put(clazz, consumers);
}
consumers.add(consumer);
}

public <T extends Event> void fire(T eventToFire, Class<T> clazz){
ConcurrentLinkedQueue<Consumer<? extends Event>> consumers = listeners.get(clazz);
if(consumers != null){
consumers.forEach(x -> x.accept(eventToFire));// <-- This blows up saying that Consumer expects type T, but I'm passing it ? extends Event
}
}

调用它的正确方法是什么,或者我是否必须使用 ConcurrentLinkedQueue 对象?我尝试抑制警告,但这似乎是一个更深层次的问题。

最佳答案

那是因为编译器不知道您在 listen 中确定了映射的键和值都由相同的参数化的方法 T 。就目前所知,这两种类型都是 ? extends Event可能彼此不兼容。

解决这个问题的唯一方法是使用显式强制转换:

consumers.stream()
.map(c -> (Consumer<T>)c )
.forEach(c -> c.accept(eventToFire));

另一方面,listen方法可以重写为:

listeners.computeIfAbsent(clazz, x -> new ConcurrentLinkedQueue<>())
.add(consumer);

这不仅更短,而且与显式检查 null 不同,它是线程安全的。

此外,fire方法不需要采取 Class<T>作为参数。您可以使用listeners.get(eventToFire.getClass())

关于java - 如何在 java 中为事件监听器模式创建并触发 Consumers<T> 集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29482417/

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