在参数中使用泛型集合

时间:2011-06-16 10:16:04

标签: java generics inheritance collections

假设你有:

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选择以这种特定方式强制执行类型安全;如果猫的列表仍然是一个动物列表,为什么一个方法期待一群动物在收到一堆猫时不愿意?

好奇,最重要的是 - 并且有机会更好地完善我的知识。

干杯, 戴夫。

3 个答案:

答案 0 :(得分:9)

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

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

然后你就能做到:

x.add(new Dog());

违反了ArrayList<Cat>只能容纳Cat个对象(或子类对象)的概念。

请阅读此内容以获取更多详细信息:Java theory and practice: Generics gotchas

答案 1 :(得分:9)

  

为什么一种方法会让一群动物不愿意接受一堆猫?

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

I think there's a spy aming us …

来电者仍然认为这是一张猫和一只狗的名单,当呼叫者试图让他们跌倒时,他们会摔倒。

答案 2 :(得分:0)

直接使用“extends”代替类:

List<? extends A>x;

如果您只使用该类作为泛型,那么所有元素都只属于此类。