在以下示例中,编译器在行上抱怨: handler.handle(INFO);错误:
方法句柄(捕获#3-of? 在类型中扩展T) Event.Handler不适用于参数 (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进行编译仍会产生类似的错误,因此这不仅仅是一个日食问题。
我的问题:
null
类型?答案 0 :(得分:5)
它被声明为某种类型的处理程序扩展T. Imagine T是Object,你传入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;
}
答案 1 :(得分:1)
回答你的第三个问题。
java中有两种类型:基元和引用类型。 实际上null是java中的一种第三种特殊类型。
还有一个特殊的null类型 表达式的类型为null,具有 无名。因为null类型没有 名字,不可能申报 null类型的变量或者要转换 到null类型。空引用 是唯一可能的价值 null类型的表达式。 null 引用总是可以转换为任何引用 参考类型。在实践中, 程序员可以忽略null类型 并假装null只是一个 可以是任何特殊文字 参考类型。