在下面的示例中,编译器在线上提示: 处理程序.handle(信息);出现错误:
The method handle(capture#3-of ? extends T) in the type Event.Handler is not applicable for the arguments (T)
即使本例中的 Handler 被声明为接受 T 的任何子类,编译器也不会接受类型 T 本身的方法调用。
public class Event<T> {
public interface Handler<U> {
public void handle(U info);
}
private final Handler<? extends T> handler;
private final T info;
public Event(Handler<? extends T> handler, T info) {
this.handler = handler;
this.info = info;
}
public void doEvent() {
handler.handle(info);
}
}
此示例的另一个有趣的功能是如果您键入:“handler”。在 Eclipse 中给出以下建议“handle(null info): void”。不知何故,类型“null”被建议作为可接受的类型。
从命令行使用 javac 编译仍然会产生类似的错误,因此这不仅仅是 Eclipse 的问题。
我的问题:
- 这是 java 编译器的正确行为吗?
- 如果这是正确的行为,我应该采取什么措施来保持事件类的类型安全?
- 什么是
null
类型?
最佳答案
它被声明为扩展 T 的某种类型的处理程序。假设 T 是对象,并且您传入 Handler<String>
。从构造函数的角度来看这很好 - 但你不会期望能够调用 handler.handle(new Object())
你会?一个Handler<String>
应该只处理字符串,而不是任意对象。
基本上,您正在寻找逆变而不是协变,因此您需要:
private final Handler<? super T> handler;
private final T info;
public Event(Handler<? super T> handler, T info) {
this.handler = handler;
this.info = info;
}
关于Java 泛型 - 接受 <? 的方法不允许使用 T 类型的对象。延伸 T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6611780/