通配符参数化不接受Object -why?

时间:2014-09-20 00:15:23

标签: java generics

以下示例来自Generics FAQ

public class Box<T> {
    private T t;

    public Box(T t) {
        this.t = t;
    }

    public void put(T t) {
        this.t = t;
    }

    public T take() {
        return t;
    }

    public static void main(String[] args) {
        Box<?> box = new Box<Object>(new Object());
        Object o = new Object();
        box.put(o); // Compiler error
        o = box.take(); // ok
    }

}

如果查看反编译版本,put()正在接受一个Object。那么为什么编译器不接受put()中的Object?

public class Box
{

    public Box(Object t)
    {
        this.t = t;
    }

    public void put(Object t)
    {
        this.t = t;
    }

    public Object take()
    {
        return t;
    }

    public static void main(String args[])
    {
        Box box = new Box(new Object());
        Object o = new Object();
        o = box.take();
    }

    private Object t;
}

1 个答案:

答案 0 :(得分:2)

对于编译器的类型检查器,Box<?>Box<Object>不同。 Box<Object>肯定会包含一个对象,因此调用put(Object)可以。 Box<?>具有未知类型参数。未知与Object不同。

例如,可能是Integer。在put(Object)上调用Box<Integer>将是一个错误。如果编译器接受了它,那么您可以将程序修改为:

Box<?> box = new Box<Integer>(1);
Object o = new Object();
box.put(o);

并且具有非常明确的类型不匹配。允许最后一行编译只会将错误推迟到运行时。

换句话说,泛型类型擦除并不意味着编译器在编译时不知道泛型类型。在信息被删除之前,它会尽力捕捉错误。