从 List 向上转换列出<超类>通过列表

发布于 2024-09-08 15:48:25 字数 614 浏览 6 评论 0 原文

我有一个类 A 和一个类 B 扩展 A

在另一个类 CI 有一个字段

private List<B> listB;

现在,由于某些不寻常的原因,我必须在 C 中实现此方法

public List<A> getList();

我尝试通过强制将 listB 字段向上转换为 List 来实现此目的 通过 List 转换:

public List<A> getList(){
    return (List<A>)(List<?>)listB;
}

客户应该这样做

List<A> list = getList();
for(A a:list){
    //do something with a
}

我做了一些测试,它似乎工作正常,但老实说,我不确定所有可能的影响。

这个解决方案正确吗?这是最好的解决方案吗?

感谢您的回答。

I have a class A and a class B extends A

In another class C I have a field

private List<B> listB;

Now, for some unusual reason, I have to implement this method in C

public List<A> getList();

I tried to do so by forcing an upcast of listB field to List<A> via a List<?> cast:

public List<A> getList(){
    return (List<A>)(List<?>)listB;
}

Clients should do

List<A> list = getList();
for(A a:list){
    //do something with a
}

I did some test and it seems work correctly, but honestly I am not sure of the all possible implications.

Is this solution correct? And Is it the best solution?

Thanks for your answers.

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

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

发布评论

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

评论(3

筱武穆 2024-09-15 15:48:25

不,这通常不是类型安全的。客户端不应该能够这样做,

List<A> list = getList();

因为否则他们可能会编写

list.add(new C()); // Where C extends A

Then将列表了解为List的原始代码,当它尝试这样做时将会出现问题使用它,假设每个元素都与 B 兼容。

您可以有效地包装原始列表以使其只读,或者使 getList 返回一个 List,这意味着客户端无论如何都无法向其中添加项目。

如果您使用的列表实现是不可修改的,那么它实际上不会导致问题 - 但我个人仍然会尽可能避免它。

No, this isn't generally type-safe. The client shouldn't be able to do

List<A> list = getList();

because otherwise they could write

list.add(new C()); // Where C extends A

Then the original code which knows about the list as a List<B> will have problems when it tries to use it, assuming that every element is compatible with B.

You could either wrap the original list to make it read-only, effectively - or make getList return a List<? extends A>, which means that clients won't be able to add items to it anyway.

If the list implementation you're using is unmodifiable, then it won't actually cause problems - but I'd still personally avoid it where possible.

琉璃梦幻 2024-09-15 15:48:25

这样做的问题是,客户端可能会无意中将 A 对象插入到实际上只是更具体的 B 对象的列表中:

c.getList().add(new A());

当您的code 尝试从列表中获取一个对象,假设它是 B,但事实并非如此。

如果您的唯一目标是让客户端迭代列表,那么最好提供一个 Iterable

public Iterable<A> getAs() { return this.theListOfAs; }

通过这个 Iterable,人们只能检查和删除元素,但不添加它们。

如果您还想禁用删除,请将 ListIterable 包装在您自己的实现中,在 remove() 时抛出 UnsupportedOperationException 被调用。

The problem with this is that clients can, unwittingly, insert A objects in what is actually a list of more specific B objects only:

c.getList().add(new A());

This will cause all kinds of breakage when your code tries to take an object from the list assuming that it's a B, but it isn't.

If your only goal is to let the client iterate over the list, it is better to hand out an Iterable<A> instead:

public Iterable<A> getAs() { return this.theListOfAs; }

Through this Iterable, one can only inspect and remove elements, but not add them.

If you want to disable removal as well, wrap the List's Iterable in your own implementation, throwing UnsupportedOperationException when remove() is called.

心在旅行 2024-09-15 15:48:25

如果您想要可变性,

List<A> getList() {
    return List.copyOf(listB);
}

您也可以返回一个 new ArrayList(listB) 。

正如其他回复所提到的,向上转换集合是不安全的,因为调用者可能会通过将错误的元素放入其中来破坏它。幸运的是,类型系统阻止您这样做,您别无选择,只能使用这些类型良好的方法复制集合,因此它可以正常工作。

也适用于地图。

Simply do this

List<A> getList() {
    return List.copyOf(listB);
}

You could as well return a new ArrayList(listB) if you want mutability.

As other responses mentioned, it is not safe for a collection to be upcast because a caller could corrupt it by putting wrong elements into it. Fortunately the type system prevents you from doing it and you have no choice but to copy the collection with these methods which are nicely typed so it just works.

Works for Maps too.

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