Java Generics:无法将List<SubClass>转换为List<SuperClass>?

2022-08-31 08:48:29

遇到这个问题:

List<DataNode> a1 = new ArrayList<DataNode>();
List<Tree> b1 = a1;  // compile error: incompatible type

其中,类型 DataNode 是 Tree 的子类型。

public class DataNode implements Tree

令我惊讶的是,这适用于数组:

DataNode[] a2 = new DataNode[0];
Tree[] b2 = a2;   // this is okay

这有点奇怪。任何人都可以对此做出解释吗?


答案 1

在第二种情况下,您看到的是数组协方差。这是一件坏事,IMO使数组中的赋值不安全 - 尽管在编译时很好,但它们在执行时可能会失败。

在第一种情况下,假设代码确实编译了,后面跟着:

b1.add(new SomeOtherTree());
DataNode node = a1.get(0);

你期望发生什么?

您可以执行以下操作:

List<DataNode> a1 = new ArrayList<DataNode>();
List<? extends Tree> b1 = a1;

...因为这样你只能从 中获取东西,并且它们保证与 兼容。你不能完全调用,因为编译器不知道它是否安全。b1Treeb1.add(...)

看看Angelika Langer的Java Generics FAQ的这一部分,了解更多信息。


答案 2

如果你必须从 到 ,并且你知道这样做是安全的,那么实现这个目标的一个丑陋的方法是做一个双重投射:List<DataNode>List<Tree>

List<DataNode> a1 = new ArrayList<DataNode>();

List<Tree> b1 = (List<Tree>) (List<? extends Tree>) a1;


推荐