列出泛型协方差

时间:2014-03-04 16:40:23

标签: java generics covariance

假设我们有两个不同的列表。

List 1可以采用任何Number参数(包括int,double,float和其他所有的Nu​​mber的子类)。

 List<Number> l1 = new ArrayList();

这样做非常合适。

    l1.add(123);
    l1.add(123.3456);

列表2扩展了Number。问题是我不能添加任何东西,我不明白为什么。另外,为什么我需要一个&lt; ?扩展某事&gt;而不只是创建一个层次结构中最高级别的列表,可以存储任何子类(如列表1)?

List<? extends Number> l2 = new ArrayList();
    l2.add(123); //Error, although Integer is a subclass of Number
    l2.add(new Integer(123)); // Wrappers don't work either
    l2.add(123.456); //Error again

3 个答案:

答案 0 :(得分:5)

调用add方法在具有? extends通配符的类上具有泛型参数的问题是编译器不知道确切的类型。它可以是List<Number>List<Integer>List<Double>List<BigInteger>。编译器必须使用泛型保留类型安全性,如果允许这样的调用,则不会保留类型安全性。您不应该被允许将Double添加到可能是List<Integer>的列表中。

此类? extends上限通配符本身可用作方法参数,其中确切类型并不重要;重要的是它的界限(在这种情况下,Number)或以下。

public void foo(List<? extends Number> list) {
    for (Number n : list) {
       // do something with some kind of Number, don't care which

答案 1 :(得分:2)

?是编译器未知的通配符。它可以是从数字派生的任何类型的实例。仿制药是为了类型安全的确切目的而实施的,因为进入的类型是未知的,所以这不起作用。

答案 2 :(得分:1)

通配符不能用于修改列表,仅用于处理列表中已包含的元素。如果您创建列表或向列表添加元素,则必须知道列表中确切包含哪些元素。

相关问题