通用外卡协方差和arraylist添加功能行为

时间:2014-03-22 13:46:43

标签: java generics

EquilateralTriangleTriangle的子类型。

List<? super EquilateralTriangle> equilateralTriangle =
        new ArrayList<Triangle>(Arrays.asList(new Triangle(), new Triangle()));
equilateralTriangle.add(new Triangle());            // doesn't work
equilateralTriangle.add(new EquilateralTriangle()); // works

据我所知List<? super EquilateralTriangle>是声明,new ArrayList<Triangle>我们告诉编译器我的arraylist是三角形类型的具体内容。那为什么编译器会在第二行抱怨?我插入了与实例化arraylist时定义的类型参数中定义的相同的值。

Java arraylist定义说:

class ArrayList<E> extends AbstractList<E>

public ArrayList(Collection<? extends E> c)

boolean add(E e); ArrayList

因此,类型E可以被称为Triangle。然后add一定不要抱怨,因为我在Triangle构造函数中传递了ArrayList。我理解中缺少什么?

2 个答案:

答案 0 :(得分:1)

看看以下陈述。显然,添加 String 可以正常工作,而添加 Object 会导致编译时错误。

List<String> items = ...;
items.add(new String()); // works
items.add(new Object()); // error

现在,让我们在您的问题中使用通配符:

List<? super String> items = ...;

在此变量声明中,?代表未知类型,即 String String 。该类型未推断/推断。它只是一个未知类型。编译器必须假设? super String可以是String。正如我们上面所看到的,您不应该将 Objects 添加到 Strings 列表中。

答案 1 :(得分:0)

nosid's answer解释了逆变部分。我只是解决这个问题:

  

为什么编译器会在第二行抱怨?我插入了与实例化arraylist时定义的类型参数中定义的相同的值。

我可以问你关于这段代码的同样问题:

Object object = new ArrayList<Triangle>();
object.add(new Triangle());

为什么这不起作用?编译器不知道objectArrayList<Triangle>吗?

答案是否定的。编译器对实例化的类型并不重要。重要的是您调用add的变量类型。