我的问题是关于Java 7中的泛型。假设我们有这样的类层次结构:
interface Animal {}
class Lion implements Animal {}
class Butterfly implements Animal {}
一样
我们还有一个班级
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:
我已阅读here有关这些问题,但其中只有Cage<?>
。但是我告诉编译器<? extends Animal>
所以T
中的Cage<T>
类型将是Animal类型的任何子类型。那么为什么它仍然会产生编译时错误?
问题#2:
如果我指定Cage<? super Animal> cage = ...
而不是Cage<? extends Animal> cage = ...
,一切正常,编译器没有说错。为什么在这种情况下它工作正常,而在上面的例子中它失败了?
答案 0 :(得分:6)
笼子必须能够容纳两种类型的动物。 “超级”说 - 它说Cage必须能够容纳所有类型的动物 - 也许还有其他一些东西,因为? super Animal
可能是动物的超类。 “延伸”说它可以容纳一些种动物 - 例如,可能只是狮子会,如:
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 1和part 2。