如何在Java中将继承对象的列表转换为对象集合?

2022-09-04 06:18:29

我有一个集合类型:

Collection<A> collecA

我的对象中有一个列表:

List<B> listB

其中 B 正在扩展 A

class B extends A { ... }

但我不能做以下事情:

collecA = listB

我不明白为什么因为集合是由List实现的。


答案 1

让我们假设一下,你可以做你所描述的:

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!

方法调用看起来没问题,因为它是一个保存 s 的集合。但是,如果允许上述分配,那么我们就有问题了,因为实际上是对实例的引用 - 我刚刚将一个添加到只能容纳s的列表中!collecA.add(new A())collecAAcollecAList<B>AB

阿斯克还说:

我不明白为什么因为集合是由List实现的。

集合是 List 的超类并不重要。即使您使用了两个列表,此分配也是非法的。

class B extends A { ... }
List<A> listA;
List<B> listB;
listA = listB;  // still an error, still leads to the same problem

关键是 List<A> 变量只能引用可以保存 As 的列表。但是,List<B> 实例不能保存 As。因此,不能为 List<A>变量(如 listA)分配对 listB 引用的 List<B>实例的引用。

或者更一般地说:BA的子类并不意味着SomeGenericClass<B>SomeGenericClass<A>的子类JLS §4.10子类型不延伸到泛型类型:T <:U并不意味着C<T> <:C<U>)


正是 Java 泛型教程中的这个例子/类比帮助我理解了这一点:

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 = ...;

但是“动物笼子”呢?英语是模棱两可的,所以确切地说,让我们假设我们正在谈论一个“全动物笼子”

Cage<Animal> animalCage = ...;

这是一个笼子,设计用于容纳各种动物,混合在一起。它必须有足够坚固的杆来容纳狮子,并且间隔足够紧密以容纳蝴蝶。
...
既然狮子是一种动物(狮子是动物的一个亚型),那么问题就变成了,“狮子笼子是一种动物笼子吗?是 的子类型吗?根据上述动物笼的定义,答案一定是“不”。这真是令人惊讶!但当你想到这一点时,这是完全有道理的:狮子笼不能被假定为蝴蝶,蝴蝶笼不能被假设为狮子。因此,两个笼子都不能被认为是“全动物”笼子:Cage<Lion>Cage<Animal>

animalCage = lionCage;  // compile-time error
animalCage = butterflyCage; // compile-time error

"


答案 2
Collection<? extends A> collecA

这修复了它。问题不在于 ,而在于泛型类型。List extends Collection