【问题标题】:Why we can't do List<Parent> mylist = ArrayList<child>(); [duplicate]为什么我们不能做 List<Parent> mylist = ArrayList<child>(); [复制]
【发布时间】:2011-08-11 10:45:33
【问题描述】:

为什么我们做不到

List<Parent> mylist = ArrayList<child>();

【问题讨论】:

  • Nitpick:Parent / Child 比喻在讨论继承时很奇怪,因为继承描述了 is a 关系。 (你会说Child Parent吗?)
  • 因为家族树或层次结构经常被用作 Java 类型层次结构的类比。虽然从语义上讲你有道理。

标签: java generics inheritance collections


【解决方案1】:

假设我们可以。那么这个程序就应该没问题了:

ArrayList<Banana> bananas = new ArrayList<Banana>();
List<Fruit> fruit = bananas;
fruit.add(new Apple());

Banana banana = bananas.get(0);

这显然不是类型安全的 - 你最终在香蕉集合中得到了一个苹果。

可以做的是:

List<? extends Fruit> fruit = new ArrayList<Banana>();

这是安全的,因为编译器不会让您尝试将添加到水果列表中。它知道这是一个某种水果的列表,所以你可以这样写:

Fruit firstFruit = fruit.get(0);

但它不知道它列出的具体水果种类,并确保你不会做错事。

参见Java generics FAQ的另一种解释。

【讨论】:

  • 我很喜欢这个解释。
  • 乔恩,您刚刚将我关于 AlignmentAssigner 的问题与此相关;我实现了扩展符号,它可以工作。一个问题:当我将填充的数组传递给扩展我的接口的实用程序方法时,该 List 将类型更改为泛型。是否可以让一个方法扩展接口,处理实现该接口的数据,然后将其作为 original 类型传回?我唯一的问题是我必须将新的通用 List 转换为使用我的实现类。
  • @rainydaymatt:不是没有使类型本身通用,不。否则,您将如何保存有关您拥有哪种类型的列表的信息?
  • 这可能是您引用的常见问题解答:angelikalanger.com/GenericsFAQ/FAQSections/…
  • @Jake88:谢谢,已编辑。
【解决方案2】:

因为它们不是同一类型。假设您有另一个Parent 的子类(Child2 用于论证),则可以将Child2 的实例放入List&lt;Parent&gt;,但将其放入实例中的类型不正确的List&lt;Child&gt;。协变继承是一个真正令人头疼的问题,并且在 Java 中只支持数组类型(它可能会导致奇怪的问题)。

【讨论】:

    【解决方案3】:

    应该是这样,因为我们可以这样做: 父 A = new Child();

    编辑:等等,实际上它有效:

    List<Parent> list = new ArrayList<Parent>(); List<ChildA> tmp = new ArrayList<ChildA>(); list.addAll(tmp); List<ChildB> tmp2 = new ArrayList<ChildB>(); list.addAll(tmp2);

    只是不支持直接投射。

    【讨论】:

      猜你喜欢
      • 2010-11-13
      • 1970-01-01
      • 1970-01-01
      • 2014-01-09
      • 1970-01-01
      • 2015-05-29
      • 2011-01-21
      • 2016-02-09
      • 1970-01-01
      相关资源
      最近更新 更多