4 回答
苹果是水果,但苹果列表不是水果列表。
如果是,你可以在苹果列表中放一根香蕉
直接转换列表是不好的,因为它颠覆了 Java 类型系统。强制转换总是会成功,但程序可能会ClassCastException
在您稍后检索项目时失败,此时错误的来源可能不清楚。
通常,您希望程序在尽可能接近错误源的位置失败。如果你强制转换列表,它可能会在有人真正尝试访问元素之前传递一段时间,到它抛出 aClassCastException
时,可能真的很难追踪到那个强制转换(至少比 if更难)该程序在演员表中失败)。
从您的评论看来,您确定其中的所有listA
内容实际上都是 aB
在这种情况下,我建议:
List<B> listB = new ArrayList(listA.size());
for (A a : listA) {
if (a == null || a instanceof B) {
listB.add((B) a);
} else {
//Either ignore or throw exception
}
}
为此,您必须了解List<A>
andList<B>
是两种不同的类型,没有层次关系,即使A
和B
是层次相关的。即使B
是 的子类A
,将 a 强制转换List<B>
为 a也是不好的,因为它可以允许您将(但不是) 的List<A>
实例添加到该列表中,并且编译器会很乐意这样做,即使它与实际的 (运行时) 不一致集合的类型。A
B
我不知道你可以在 Java 中规避这一点,但如果你能做到,那只是因为类型擦除:因为 Java 创建了一个类,例如List<Object>
,对于该泛型类的不同“实现”,它只是在你的代码中添加强制转换在编译它之前。这与(比如说)C# 形成对比,C# 实际上List<T>
只使用作为“编译”模板(称为“通用定义”)来按需创建具体类型。
泛型的工作方式有所不同,因此list< B >不是list< A >类型,尽管B是A的类型。