Java泛型 - 接受<! - 的方法不允许使用类型为T的对象?延伸T - >

时间:2011-07-07 13:57:43

标签: java generics

在以下示例中,编译器在行上抱怨: 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进行编译仍会产生类似的错误,因此这不仅仅是一个日食问题。

我的问题:

  1. 这是java编译器的正确行为吗?
  2. 如果这是正确的行为,我应该做些什么来保持我的事件类的类型安全?
  3. 什么是null类型?

2 个答案:

答案 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只是一个   可以是任何特殊文字   参考类型。

source