gpt4 book ai didi

Java 泛型/通配符类型不匹配

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

我正在尝试构建一个 Java 事件发射器,它将具有一个映射到事件名称的回调列表(实现消费者接口(interface))。

import java.util.HashMap;
import java.util.PriorityQueue;
import java.util.function.Consumer;
import java.util.EventObject;

public class Emitter
{
protected HashMap<String, PriorityQueue<Consumer<? extends EventObject>>> listeners;

public Emitter()
{
this.listeners = new HashMap<String, PriorityQueue<Consumer<? extends EventObject>>>();
}

public Emitter on(String eventName, Consumer<? extends EventObject> listener)
{
if (!this.listeners.containsKey(eventName)) {
this.listeners.put(eventName, new PriorityQueue<Consumer<? extends EventObject>>());
}

this.listeners.get(eventName).add(listener);

return this;
}

public <E extends EventObject> Emitter emit(E event)
{
String eventName = event.getClass().getName();

for (Consumer<? extends EventObject> listener : this.listeners.get(eventName)) {
listener.accept(event);
}

return this;
}
}

我得到这个编译错误:

Emitter.java:31: error: incompatible types: E cannot be converted to CAP#1
listener.accept(event);
^
where E is a type-variable:
E extends EventObject declared in method <E>emit(E)
where CAP#1 is a fresh type-variable:
CAP#1 extends EventObject from capture of ? extends EventObject

但捕获的类型显然是 的子类型,因此它应该可以工作(但我知道我遗漏了一些东西)。

用法应该是这样的(当然 OpenEvent 和 CloseEvent 扩展了 EventObject):

Emitter em = new Emitter();
em.on("open", (OpenEvent e) -> e.doOpen());
em.on("close", (CloseEvent e) -> e.doClose());
em.emit(new OpenEvent());
em.emit(new CloseEvent());

我想可以做到这种类型安全,因为我可以通过 lambda 函数指定消费者对象的类型。但是如何呢?

最佳答案

发生这种情况是因为 listener是类型:Consumer<? extends EventObject> (因此,它是一个扩展了 Consumer 的某种特定但未知类型的 EventObject ),但您希望它接受 E 类型的事件.编译器无法检查通配符指示的未知类型是否等于类型 E .

为什么要使用通配符?最好摆脱它们,然后做这样的事情:

public class Emitter<E extends EventObject>
{
protected HashMap<String, PriorityQueue<Consumer<E>>> listeners;

public Emitter()
{
this.listeners = new HashMap<String, PriorityQueue<Consumer<E>>>();
}

public Emitter on(String eventName, Consumer<E> listener)
{
if (!this.listeners.containsKey(eventName)) {
this.listeners.put(eventName, new PriorityQueue<Consumer<E>>());
}

this.listeners.get(eventName).add(listener);

return this;
}

public Emitter emit(E event)
{
String eventName = event.getClass().getName();

for (Consumer<E> listener : this.listeners.get(eventName)) {
listener.accept(event);
}

return this;
}
}

注意:带有 ? extends EventObject 的通配符类型是否意味着您可以将任何扩展 EventObject 的对象传递给它;它指定了一个特定但未知的类型,它扩展了 EventObject .因为确切的类型是什么是未知的,所以这限制了您可以用它做什么。

关于Java 泛型/通配符类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23082949/

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