小编典典

泛型不允许将A的超级类型添加到列表中

java

我在列表上使用通配符和下限泛型,但是编译器抛出错误。

码:

int intStart = 0;       
Number num = new Integer(2);                
List<? super Integer> listOfNumbers = new ArrayList<>();
listOfNumbers.add(intStart);
listOfNumbers.add(num); //throws compiler error

错误:

类型List中的方法add(capture#8-of?super Integer)不适用于参数(Number)

使用List<? super Integer>,应该允许我添加任何类型Integer或其超类型的对象,例如Number或Object。我已经进行了一些SO讨论,但是找不到为什么我应该克服错误。


阅读 207

收藏
2020-09-28

共1个答案

小编典典

使用List<? super Integer>,应该允许我添加Integer类型或其超类型的任何对象,例如Number或Object。

不对 List<? super Integer>并不意味着 可以容纳Integer的任何超类型的列表 。这意味着 其泛型可能是
Integer的某些 特定
超类型的列表
。因此,它实际上可能是List<Object>List<Number>List<Integer>。所有这些列表类型都可以包含一个Integer,但不能说相同Number。一个Number可能是一个Double或一Long,这是不是在允许的List<Integer>

为了更具体一点,请考虑以下代码段:

Long longValue = 2L;
List<Integer> listOfIntegers = new ArrayList<>();
// listOfIntegers.add(longValue);

带注释的行显然不应该编译,也不应该编译。但是,如果我们添加以下内容呢?

Number longAsNumber = longValue;
List<? super Integer> listOfSuper = listOfIntegers;
listOfSuper.add(longAsNumber);

这相当于您的问题中的代码段。最后一行应该编译吗?如果这样,它将违反的通用不变式List<Integer>


根据您的评论,List<? super Integer>在您的示例中确实是不必要的。更常见的情况是为方法参数增加灵活性。例如一种方法

void addInt(List<Integer> list) {
    list.add(1);
}

将只能接受List<Integer>,这将是不必要的限制。将参数类型更改为List<? super Integer>会允许该方法接受List<Integer>以及List<Number>,其中任何一个都可以包含一个Integer值。

仅当列表 使用相关 的泛型类型时,此方法才有效。如果该方法尝试从列表中 产生
值,则Object由于我们没有确定的超类型,将被迫假定它们为类型。

2020-09-28