泛型中的通配符:"? super T" 能够正常工作,而 "? extends T" 却不能?

5
我的问题是关于Java 7中的泛型。假设我们有这样的类层次结构:
interface Animal {}    
class Lion implements Animal {}    
class Butterfly implements Animal {}

就像在Java泛型教程中一样

此外,我们还有一个类

class Cage<T> {
    private List<T> arr = new ArrayList<>();
    public void add(T t) {
        arr.add(t);
    }
    public T get() {
        return arr.get(0);
    }
}

这里是使用该类的代码:

public static void main(String[] args) {
        Cage<? extends Animal> cage = new Cage<>();
        Animal a = cage.get(); //OK
        cage.add(new Lion()); //Compile-time error
        cage.add(new Butterfly()); //Compile-time error   
    }

问题1:

我在这里读到了这些问题,但只有像Cage<?>这样的东西。但是我告诉编译器<? extends Animal>,所以Cage<T>中的类型T将是Animal类型的任何子类型。那么为什么它仍然会出现编译时错误?

问题2:

如果我指定Cage<? super Animal> cage = ...而不是Cage<? extends Animal> cage = ...,一切都正常工作,编译器没有报错。为什么在这种情况下它能正常工作,而在上面的例子中它失败了?

1个回答

6

这个笼子必须能够容纳两种类型的动物。"super"表示它可以容纳所有类型的动物,也许还有其他一些东西,因为? super Animal可能是Animal类的超类。"extends"表示它可以容纳某些类型的动物 - 例如只能容纳狮子:

Cage<? extends Animal> cage = new Cage<Lion>();

这是一个有效的陈述,但显然狮子笼不可能容纳蝴蝶,因此:
cage.add(new Butterfly());   

无法编译。该语句
cage.add(new Lion());

无法编译,因为Java在这里查看的是笼子的声明- Cage<? extends Animal> - 而不是当前分配给它的对象 (Cage<Lion>)。

我知道的最好的泛型描述在O'Reilly's Java in a Nutshell中。该章节可以在网上免费阅读- part 1part 2


而且 cage.add(new Lion()) 也无法编译。 - maks
1
根据Java教程,“super”表示它可以容纳所有作为Animal超类型的类型:“因此,代码<? super Animal>将被解释为“一个未知类型,它是Animal的超类型,可能是Animal本身”。但是,狮子和蝴蝶都不是Animal的超类型,为什么它还能工作呢? - maks
<? super Animal> 理解为控制哪些类可以被赋值给变量 "cage",而不是控制 cage 可以容纳哪些对象。因此,这意味着 Cage 必须是 Cage<Animal 或其超类>,这意味着它可以处理所有动物。这样理解有帮助吗?这确实令人困惑! - Ed Staub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接