使用List,您知道所拥有的绝对是动物列表。实际上,所有这些都不一定完全是“动物”,它们也可以是派生类型。例如,如果您有动物清单,那么一对夫妇可能是山羊,其中一些可能是猫,等等,对吗?
例如,这是完全有效的:
List aL= new List();
aL.add(new Goat());
aL.add(new Cat());
Animal a = aL.peek();
a.walk(); // assuming walk is a method within Animal
当然,以下将不会是有效的:
aL.peek().meow(); // we can't do this, as it's not guaranteed that aL.peek() will be a Cat
使用List extends Animal>,您可以声明要处理的列表的类型。
例如:
List extends Animal> L;
实际上,这不是 L可以容纳的对象类型的声明。这是关于L可以引用哪些列表的声明。
例如,我们可以这样做:
L = aL; // remember aL is a List of Animals
但是现在,所有编译器都知道L是它是[Animal或Animal的子类型]的列表
因此,以下内容无效:
L.add(new Animal()); // throws a compiletime error
因为据我们所知,L可能引用的是山羊列表-我们无法在其中添加动物。
原因如下:
List gL = new List(); // fine
gL.add(new Goat()); // fine
gL.add(new Animal()); // compiletime error
在上面,我们试图将动物铸造为山羊。那是行不通的,因为这样做之后,如果我们试图让Animal像山羊一样做“头撞”怎么办?我们不一定知道动物可以做到这一点。