generics中的通配符:“? 超级T“工作时”? 延伸T“不?

我的问题是关于Java 7中的generics。假设我们有这样的类层次结构:

interface Animal {} class Lion implements Animal {} class Butterfly implements Animal {} 

就像在Java Generics Tutorial中一样

我们还有一堂课

 class Cage { private List 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 cage = new Cage(); Animal a = cage.get(); //OK cage.add(new Lion()); //Compile-time error cage.add(new Butterfly()); //Compile-time error } 

问题#1:

我在这里读过这些问题,但就像Cage 。 但我告诉编译器 所以Cage T类型将是Animal类型的任何子类型。 那为什么它仍然会产生编译时错误?

问题2:

如果我指定Cage cage = ... Cage cage = ...而不是Cage cage = ... Cage cage = ...一切正常,编译器没有说什么不好。 为什么在这种情况下它工作正常,而在上面的例子中失败?

笼子必须能够容纳两种类型的动物。 “超级”说 – 它说凯奇必须能够容纳所有类型的动物 – 也许还有其他一些东西,因为? super Animal ? super Animal可能是? super Animal的超类。 “延伸”说它可以容纳某些种类的动物 – 例如,可能只是狮子会,如:

 Cage cage = new Cage(); 

这将是一个有效的陈述,但显然狮子笼不会持蝴蝶,所以

 cage.add(new Butterfly()); 

不会编译。 该声明

 cage.add(new Lion()); 

也不会编译,因为这里的Java正在查看笼子的声明 – Cage Cage – 不是现在分配给它的对象( Cage )。

我所知道的generics的最佳描述是在O’Reilly的Java中的Nutshell中 。 本章免费在线 – 第1 部分和第2部分 。