Kar*_*och 11 java generics collections
我有一个集合类型:
Collection<A> collecA
Run Code Online (Sandbox Code Playgroud)
我的对象中有一个列表:
List<B> listB
Run Code Online (Sandbox Code Playgroud)
B在哪里延伸A.
class B extends A { ... }
Run Code Online (Sandbox Code Playgroud)
但我不能做到以下几点:
collecA = listB
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么Collection是由List实现的.
Ber*_*t F 16
让我们假设您可以做您所描述的内容:
class B extends A { ... }
Collection<A> collecA;
List<B> listB;
collecA = listB; // normally an error, but lets pretend its allowed
collecA.add(new A()); // PROBLEM!
Run Code Online (Sandbox Code Playgroud)
方法调用collecA.add(new A())看起来没问题,因为collecA是一个包含As 的集合.但是,如果允许上面的赋值,那么我们就会遇到一个问题,因为collecA它实际上是对一个List<B>实例的引用- 我只是添加了A一个只能容纳Bs 的列表!
阿斯克尔还说:
我无法理解为什么Collection是由List实现的.
Collection是List的超类并不重要.即使您使用了两个列表,此分配也是非法的.
class B extends A { ... }
List<A> listA;
List<B> listB;
listA = listB; // still an error, still leads to the same problem
Run Code Online (Sandbox Code Playgroud)
关键是List<A> 变量只能引用List可以保存As的s.但是,一个List<B> 实例无法容纳As.因此,类似的List<A> 变量listA不能被赋予对引用的List<B> 实例的引用listB.
或者更一般地讲:B是的子类,A并没有暗示SomeGenericClass<B>是的一个子类SomeGenericClass<A>(JLS§4.10:分型不通过泛型类型延伸:T <: U并不意味着C<T> <: C<U>.)
这个来自Java Generics Tutorial的示例/类比帮助我理解了这一点:
http://java.sun.com/docs/books/tutorial/java/generics/subtyping.html
"如果你想到有形物体 - 你可以实际想象的东西 - 比如笼子,理解为什么会变得容易得多:
// A cage is a collection of things, with bars to keep them in.
interface Cage<E> extends Collection<E>;
...
Cage<Lion> lionCage = ...;
Cage<Butterfly> butterflyCage = ...;
Run Code Online (Sandbox Code Playgroud)
但是"动物笼子"呢?英语含糊不清,所以准确地说我们假设我们谈的是"全动物笼子":
Cage<Animal> animalCage = ...;
Run Code Online (Sandbox Code Playgroud)
这是一个笼子,旨在容纳各种动物,混合在一起.它必须具有足够坚固的杆以容纳在狮子中,并且足够紧密地隔开以容纳在蝴蝶中.
......
由于狮子是一种动物(狮子是动物的一种亚型),因此问题就变成了,"狮子笼是一种动物笼吗?是Cage<Lion>一种亚型Cage<Animal>吗?".通过动物笼的上述定义,答案必须是"否".这太令人惊讶了!但是当你想到它时,它就变得非常有意义了:狮子笼不能被认为是留在蝴蝶中,并且不能认为蝴蝶笼藏在狮子里.因此,两个笼子都不能被视为"全动物"笼子:
animalCage = lionCage; // compile-time error
animalCage = butterflyCage; // compile-time error
Run Code Online (Sandbox Code Playgroud)
"
Boz*_*zho 10
Collection<? extends A> collecA
Run Code Online (Sandbox Code Playgroud)
这解决了它.问题不在于List extends Collection,而是泛型类型.
Java泛型不是协变的.
有关更多详细信息,请参阅Java Theory and Practice:Generics Gotchas.
该页面显示了一个简单的例子,如果它是协变的,它将破坏类型系统:
想象一下,您可以将List <Integer>分配给List <Number>.然后,以下代码将允许您将不是Integer的内容放入List <Integer>:
List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415)); // ERROR: Adds a float to li, which is a list of Integers!
Run Code Online (Sandbox Code Playgroud)