我遇到了有关Java泛型的问题。
我正在尝试制作一个监听器(称为SomeEventListener
)来监听SomeEvent
的发生。这些事件的结果具有特定的类型。我希望通过方法getResult()
检索该结果,该方法的返回类型为T
。触发该事件后,将调用eventOccurred(SomeEvent<T>)
方法。
SomeEvent类:
public class SomeEvent<T> {
private T result;
public SomeEvent(T result) {
this.result = result;
}
public T getResult() {
return this.result;
}
}
SomeEventListener类:
public interface SomeEventListener<T> {
void eventOccurred(SomeEvent<T> event);
}
另一个班级
public class AnotherClass {
ArrayList<SomeEventListener<?>> listeners = new ArrayList<SomeEventListener<?>>();
<T> void fireSomethingOccursEvent(SomeEvent<T> event) {
for (SomeEventListener<?> listener : this.listeners) {
listener.eventOccurred(event); // MARKED LINE
}
}
}
但是,Eclipse在MARKED LINE上给出了一个错误:
SomeEventListener 类型的方法eventOccurred(SomeEvent )不适用于参数(SomeEvent )
我怀疑为什么会发生这种情况-可能与泛型和类型擦除有关-但我无法解决。
我的问题:
为什么上述代码无效?
如何修复代码?
注意:有关泛型和/或类型擦除的帖子很多;但是,我找不到这个问题的答案。如果您认为其他答案合适,请链接到它。
最佳答案
您有一个SomeEventListener<?>
,其方法为void eventOccurred(SomeEvent<?> event)
(将?
替换为T
)。
对于某些完全不相关的SomeEvent<T>
,您也有一个T
。
您不能将其转换为SomeEvent<?>
-实际上,除SomeEvent<?>
之外,您无法将任何内容转换为null
。 ?
的意思是“我不知道这个类型的参数是什么。”
例如,如果您的代码被允许,则此代码将编译,但传递错误的类型:
AnotherClass ac = new AnotherClass();
ac.listeners.add(new SomeEventListener<Integer>() {
void eventOccurred(SomeEvent<Integer> event) {
System.out.println(event.intValue());
}
});
SomeEvent<String> event = new SomeEvent<String>("Hello");
ac.fireSomethingOccursEvent(event);
现在,
fireSomethingOccursEvent
将采用SomeEvent<String>
并将其传递给SomeEventListener<Integer>
。显然,这是不允许的-因此,这是不允许的。