如何创建和激发消费者群体<;T>;在java中用于事件侦听器模式
我正在尝试创建一个非常标准的事件侦听器/广播系统。现在只是玩弄不同的想法,看看它们在我们的领域是如何工作的 我遇到的问题是,我似乎找不到使用泛型调用消费者的正确语法如何创建和激发消费者群体<;T>;在java中用于事件侦听器模式,java,events,Java,Events,我正在尝试创建一个非常标准的事件侦听器/广播系统。现在只是玩弄不同的想法,看看它们在我们的领域是如何工作的 我遇到的问题是,我似乎找不到使用泛型调用消费者的正确语法 private ConcurrentHashMap<Class<? extends Event>, ConcurrentLinkedQueue<Consumer<? extends Event>>> listeners; public <T extends Event>
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
}
}
private ConcurrentHashMap这是因为编译器不知道您在listen
方法中确保映射的键和值都由相同的t
参数化。据它所知,这两种类型都是?扩展事件
可能彼此不兼容
解决此问题的唯一方法是使用显式强制转换:
consumers.stream()
.map(c -> (Consumer<T>)c )
.forEach(c -> c.accept(eventToFire));
不仅如此,与显式检查null不同,它是线程安全的
另外,fire
方法不需要将Class
作为参数。您可以使用监听器.get(eventToFire.getClass())
listeners.computeIfAbsent(clazz, x -> new ConcurrentLinkedQueue<>())
.add(consumer);