2
我想構建一個Java事件發射器,它將有一個使用事件名稱映射的回調(實現Consumer接口)列表。Java通用/通配符類型不匹配
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函數。但是如何?
但是'發射器'不會是一個異構容器嗎? –
這會綁定一個Emitter實例到單個EventObject子類型嗎?我試圖讓Emitter實例能夠偵聽EventObject的不同子類型,因爲我只在使用正確子類型定義的lambda函數內部使用特定的子類型方法作爲參數。 –
不,那麼'Emitter'不會是一個異構容器,它確實將'Emitter'綁定到一個'EventObject'子類型。我不認爲這是完全類型安全的方式,沒有強制轉換。 – Jesper