将 List<SubClass> 转换为 List<BaseClass> 的最有效方法

新手上路,请多包涵

我有一个 List<SubClass> 我想将其视为 List<BaseClass> 。看起来这应该不是问题,因为将 SubClass 转换为 BaseClass 很容易,但我的编译器抱怨说转换是不可能的。

那么,获取与 List<BaseClass> 相同对象的引用的最佳方法是什么?

现在我只是制作一个新列表并复制旧列表:

 List<BaseClass> convertedList = new ArrayList<BaseClass>(listOfSubClass)

但据我了解,必须创建一个全新的列表。如果可能的话,我想要参考原始列表!

原文由 Riley Lark 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 351
2 个回答

这种分配的语法使用通配符:

 List<SubClass> subs = ...;
List<? extends BaseClass> bases = subs;

重要的是要意识到 List<SubClass> 不能List<BaseClass> 互换。保留对 List<SubClass> 的引用的代码将期望列表中的每个项目都是 SubClass 。如果另一部分代码将列表称为 List<BaseClass> ,编译器将不会在插入 BaseClassAnotherSubClass 时报错但这将导致第一段代码出现 ClassCastException ,它假设列表中的所有内容都是 SubClass

通用集合的行为与 Java 中的数组不同。数组是协变的;也就是说,允许这样做:

 SubClass[] subs = ...;
BaseClass[] bases = subs;

这是允许的,因为数组“知道”其元素的类型。如果有人试图在数组中存储不是 SubClass 实例的内容(通过 bases 引用),将抛出运行时异常。

通用集合 _不_“知道”它们的组件类型;此信息在编译时被“删除”。因此,当发生无效存储时,它们无法引发运行时异常。相反,当从集合中读取值时,将在代码中某个遥远的、难以关联的点引发 ClassCastException 。如果您注意编译器关于类型安全的警告,您将在运行时避免这些类型错误。

原文由 erickson 发布,翻译遵循 CC BY-SA 2.5 许可协议

埃里克森已经解释了为什么你不能这样做,但这里有一些解决方案:

如果您只想从基本列表中取出元素,原则上您的接收方法应声明为采用 List<? extends BaseClass>

但如果不是并且您无法更改它,则可以使用 Collections.unmodifiableList(...) 包装列表,这允许返回参数参数超类型的列表。 (它通过在插入尝试时抛出 UnsupportedOperationException 来避免类型安全问题。)

原文由 Paŭlo Ebermann 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题