- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
此问题与 How to create and fire a collection of Consumers<T> in java for an event listener pattern 相关。我试图使用事件集合来帮助批量操作,但到目前为止我似乎无法提供通用定义的正确配置。
这是到目前为止我的代码。
private ConcurrentHashMap<Class<? extends Event>, ConcurrentLinkedQueue<Consumer<Collection<? extends Event>>>> listeners;
public <T extends Event> void listen(Class<T> clazz, Consumer<Collection<T>> consumer){
ConcurrentLinkedQueue<Consumer<Collection<T>>> consumers = listeners.get(clazz);
if (consumers == null) {
consumers = new ConcurrentLinkedQueue<>();
listeners.put(clazz, consumers); // Complains that consumers is not the type Collection<? extends Event>
}
consumers.add(consumer);
}
public <T extends Event> void fire(Collection<T> eventToFire){
ConcurrentLinkedQueue<Consumer<Collection<? extends Event>>> consumers = listeners.get(eventToFire.getClass());
if(consumers != null){
consumers.forEach(x -> x.accept(eventToFire));
}
}
我尝试过设置ConcurrentLinkedQueue<Consumer<Collection<T>>> consumers = listeners.get(clazz);
成为ConcurrentLinkedQueue<Consumer<Collection<? extends Event>>> consumers = listeners.get(clazz);
但随后它提示 consumers.add(consumer);
不是 Consumer<Collection<T>>
类型.
除了 consumers.add((Consumer<Collection<? extends Event>>)(Object)consumer);
之外,似乎没有任何转换可以解决这个问题。 ,但这对我来说看起来很可怕,而且似乎我一定错过了一些东西,或者搞砸了一些东西,因为这似乎不应该是一个必需的步骤。
最佳答案
您希望编译器知道键的类型是否为 Class<T>
(其中 T extends Event
),则该值为 ConcurrentLinkedQueue<Consumer<Collection<T>>>
。
不幸的是,没有办法表达这个事实。但是,您知道这是真的,因为您放入映射中的唯一键/值对都具有这种形式。因此,加入 Actor 阵容是安全的,但我还会添加一条评论来解释为什么可以。
值的类型实际上应该是
ConcurrentLinkedQueue<? extends Consumer<? extends Collection<? extends Event>>>
不是
ConcurrentLinkedQueue<Consumer<Collection<? extends Event>>>
后者是 Consumers
的队列必须能够接受扩展 Event
的任何类型的集合,但你只想要 Consumer
接受 Collections
某些特定类型 T
延伸Event
。理解这一点非常困难,但请记住,您通常需要 ? extends
当您将通配符与嵌套类型参数混合时,在每个级别上。
最后,eventToFire.getClass()
不是您想要的,因为这返回某种集合类型的类,而您的键的类型为 Class<? extends Event>
。由于类型删除,您无法在运行时从集合中获取类型参数,因此您需要显式传递 clazz
至fire
也是如此。
通过这些更改,代码变为
private ConcurrentHashMap<Class<? extends Event>, ConcurrentLinkedQueue<? extends Consumer<? extends Collection<? extends Event>>>> listeners;
public <T extends Event> void listen(Class<T> clazz, Consumer<Collection<T>> consumer){
ConcurrentLinkedQueue<Consumer<Collection<T>>> consumers = (ConcurrentLinkedQueue<Consumer<Collection<T>>>) listeners.get(clazz);
if (consumers == null) {
consumers = new ConcurrentLinkedQueue<>();
listeners.put(clazz, consumers);
}
consumers.add(consumer);
}
public <T extends Event> void fire(Class<T> clazz, Collection<T> eventToFire){
ConcurrentLinkedQueue<Consumer<Collection<T>>> consumers = (ConcurrentLinkedQueue<Consumer<Collection<T>>>) listeners.get(clazz);
if(consumers != null){
consumers.forEach(x -> x.accept(eventToFire));
}
}
唯一需要的转换是在假设键和值匹配的两行中,但这是您可以做的最好的事情。
关于java - 如何在带有通配符的泛型映射中使用带有类型化参数的泛型集合 (Java),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29504373/
我是一名优秀的程序员,十分优秀!