通过 List<subclass> 向上转换到 List<superclass> 通过 List<?>

2022-09-04 02:20:23

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

在另一个C类中,我有一个字段

private List<B> listB;

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

public List<A> getList();

我试图通过List强制将listB字段的向上转换强制为List来做到这一点:<A><?>

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

客户应该做的

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

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

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

感谢您的回答。


答案 1

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

List<A> list = getList();

因为否则他们可以写

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

然后,知道列表作为a的原始代码在尝试使用它时会遇到问题,假设每个元素都与 兼容。List<B>B

您可以包装原始列表以使其有效地成为只读 - 或者返回一个 ,这意味着客户端无论如何都无法向其添加项目。getListList<? extends A>

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


答案 2

这样做的问题是,客户端可以在不知不觉中将对象插入到实际上仅包含更具体对象的列表中:AB

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

当您的代码尝试从列表中获取对象时,这将导致各种中断,假设它是 一个 ,但事实并非如此。B

如果您的唯一目标是让客户端循环访问列表,则最好分发一个:Iterable<A>

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

通过这种方式,只能检查和删除元素,而不能添加它们。Iterable

如果您还想禁用删除,请将 's 包装在您自己的实现中,并在调用时引发。ListIterableUnsupportedOperationExceptionremove()