【问题标题】:Using generic collections in arguments在参数中使用泛型集合
【发布时间】:2011-09-16 06:00:56
【问题描述】:

假设你有:

public interface A {}

public class B implements A {}

public class C {
  void foo (List<A>) {}
}

public class Test {
  //Declaration one
  List<A> x = new List<A>();

  //Declaration two
  List<A> x = new List<B>();

  B b = new B();
  x.add(b);


  new C().foo(x);
}

现在显然声明一是执行此操作的正确方法,但声明二会出现编译错误。我想知道为什么 Java 选择以这种特定方式强制执行类型安全;如果 Cats 列表仍然是 Animals 列表,为什么期望动物列表的方法拒绝接收一堆猫?

好奇心,比什么都重要 - 并且有机会更好地完善我的知识。

干杯, 戴夫。

【问题讨论】:

  • 附带说明,我知道我们可以将 C 中的方法更改为以下内容: void foo(List extends A>) {} 但我仍然想知道为什么这种替换不无论如何都不会“自动”发生:)

标签: java generics inheritance collections


【解决方案1】:

Java 泛型不是协变的。如果你能做到这一点:

ArrayList<Animal> x = new ArrayList<Cat>();

那么你就可以做到:

x.add(new Dog());

这违反了ArrayList&lt;Cat&gt; 只能包含Cat 对象(或子类对象)的概念。

阅读本文了解更多详情:Java theory and practice: Generics gotchas

【讨论】:

  • 谢谢您的好先生。一个非常有用的链接来回答我的问题。
【解决方案2】:

为什么一个期望动物列表的方法拒绝接收一群猫?

因为您可以将任何动物添加到该列表中,而不仅仅是猫。这可能会导致包含狗的猫列表,如下所示:

调用者仍然认为这是一个猫列表,当调用者试图让它们跌倒时,一只狗死了。

【讨论】:

    【解决方案3】:

    直接使用“扩展”而不是类:

    List<? extends A>x;
    

    如果您仅将类用作泛型,则所有元素都必须仅属于该类。

    【讨论】:

      猜你喜欢
      • 2019-09-06
      • 1970-01-01
      • 1970-01-01
      • 2015-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多