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

发布于 2024-08-30 17:16:55 字数 311 浏览 3 评论 0原文

我有一个集合类型:

Collection<A> collecA

我的对象中有一个列表:

List<B> listB

其中 B 扩展 A

class B extends A { ... }

但我不能执行以下操作:

collecA = listB

我不明白为什么,因为 Collection 是由 List 实现的。

I've a collection type:

Collection<A> collecA

And I've a list in my object:

List<B> listB

Where B is extending A

class B extends A { ... }

But I can't do the following:

collecA = listB

I can't understand why since Collection is implemented by List.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

余厌 2024-09-06 17:16:55

让我们假设您可以执行您所描述的操作:

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!

方法调用 collecA.add(new A()) 看起来没问题,因为 collecA 是一个集合
包含 A。然而,如果允许上述分配,那么我们有一个
问题是因为 collecA 实际上是对 List 实例的引用 - 我只是
A 添加到只能容纳 B 的列表中!

阿斯克还说:

我不明白为什么,因为 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

关键是 List 变量只能引用可以容纳 AList s。但是,List实例不能容纳A。因此,像 listA 这样的 List 变量 不能分配对 List 的引用< em>实例由listB引用。

或者更一般地说:BA的子类> 是否暗示 SomeGenericClassSomeGenericClass 的子类 (JLS §4.10子类型不通过泛型类型扩展:< code>T <: U 并不意味着 C<: C)


这是来自 的示例/类比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的子类型吗?” >笼子<动物>?”。根据上述动物笼的定义,答案一定是“否”。这太令人惊讶了!但仔细想想,这是完全有道理的:不能假设狮子笼里关着蝴蝶,也不能假设蝴蝶笼里关着狮子。因此,这两个笼子都不能被视为“全动物”笼子:

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

Let's assume for a moment you could do what you describe:

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!

The method call collecA.add(new A()) appears okay since collecA is a collection
that holds As. However, if the above assignment were allowed, then we have a
problem becausecollecA is really reference to a List<B> instance - I just
added an A into a list that can only hold Bs!

Asker also said:

I can't understand why since Collection is implemented by List.

It doesn't matter that Collection is a superclass of List. This assignment is illegal even if you used two lists.

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

The key is that the List<A> variable can reference only Lists that can hold As. However, a List<B> instance cannot hold As. Therefore, a List<A> variable like listA cannot be assigned a reference to a List<B> instance referred to bylistB.

Or more generally speaking: B being a subclass of A does not imply that SomeGenericClass<B> is a subclass of SomeGenericClass<A> (JLS §4.10: Subtyping does not extend through generic types: T <: U does not imply that C<T> <: C<U>.)


It was this example/analogy from the Java Generics Tutorial that helped me understand this:

http://java.sun.com/docs/books/tutorial/java/generics/subtyping.html

"Understanding why becomes much easier if you think of tangible objects — things you can actually picture — such as a cage:

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

But what about an "animal cage"? English is ambiguous, so to be precise let's assume we're talking about an "all-animal cage":

Cage<Animal> animalCage = ...;

This is a cage designed to hold all kinds of animals, mixed together. It must have bars strong enough to hold in the lions, and spaced closely enough to hold in the butterflies.
...
Since a lion is a kind of animal (Lion is a subtype of Animal), the question then becomes, "Is a lion cage a kind of animal cage? Is Cage<Lion> a subtype of Cage<Animal>?". By the above definition of animal cage, the answer must be "no". This is surprising! But it makes perfect sense when you think about it: A lion cage cannot be assumed to keep in butterflies, and a butterfly cage cannot be assumed to hold in lions. Therefore, neither cage can be considered an "all-animal" cage:

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

"

神仙妹妹 2024-09-06 17:16:55
Collection<? extends A> collecA

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

Collection<? extends A> collecA

This fixes it. The problem is not the List extends Collection, but the generic types instead.

逆流 2024-09-06 17:16:55

Java 泛型不是协变的。

请参阅 Java 理论与实践:泛型陷阱 了解更多详细信息。

该页面显示了一个简单的示例,如果它是协变的,则会破坏类型系统:

想象一下您可以分配一个 List到列表。然后,以下代码将允许您将非整数的内容放入列表中:

List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415)); // ERROR: Adds a float to list, which is a list of Integers!

Java generics are not covariant.

See Java Theory and Practice: Generics Gotchas for further details.

The page shows a simple example that would havoc the type-system if it was covariant:

Imagine you could assign a List<Integer> to a List<Number>. Then the following code would allow you to put something that wasn't an Integer into a List<Integer>:

List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415)); // ERROR: Adds a float to list, which is a list of Integers!

您可以分配 List到 Collection,但不是 List到集合

想象一下,如果这是可能的,会发生什么:

List<B> = new ArrayList<B>();
Collection<A> collecA = listB; //Assume that this line compiles
collecA.add(new A());
B item = listB.get(0); //ClassCastException!

如您所见,我们通过将具体类型 A 的实例添加到本应仅包含类型 B(或后代)对象的集合中,“欺骗”了泛型类型系统。
因此,执行隐式转换为 B 的最后一行失败并出现 ClassCastException。有什么问题吗?编译器无法保证类型安全,这违反了 Java 泛型原则之一。

因此,已决定将List添加到列表B中。是集合,但不是列表; (或集合)。

作为旁注,有趣的是,数组不遵循相同的规则:String[] 一个 Object[],并且赋值是合法的。

You can assign List<B> to Collection<B>, but not List<B> to Collection<A>.

Imagine what would happen if this were possible:

List<B> = new ArrayList<B>();
Collection<A> collecA = listB; //Assume that this line compiles
collecA.add(new A());
B item = listB.get(0); //ClassCastException!

As you see, we "fooled" the generics type system, by adding an instance of concrete type A to a collection that was supposed to have only objects of type B (or descendants).
As a consequence, the last line which performs an implicit cast to B fails with a ClassCastException. What's wrong with it? The compiler can't guarantee type safety, and that's against one of the Java generics principles.

Therefore, it has been decided that List<B> is Collection<B>, but NOT List<A> (or Collection<A>).

As a side comment, it is interesting to note that arrays don't follow the same rules: String[] is an Object[], and assignments are legal.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文