为什么不能在上限泛型列表中添加元素?

use*_*979 14 java

我有一个带有上限泛型的列表.

 List<? extends Number> l = new ArrayList<>();
 l.add(new Integer(3));  //ERROR
 l.add(new Double(3.3)); // ERROR
Run Code Online (Sandbox Code Playgroud)

我不明白这个问题,因为Integer和Double扩展了Number.

Tob*_*obb 24

List<? extends Number>并不意味着"一个可以容纳子类的所有对象的列表Number",它意味着"一个参数化为一个扩展的具体类的列表Number".它不是你定义的列表本身的内容,它是分配给变量的实际列表对象的参数化类型(男孩,这比理解它更难解释:))

所以,你可以这样做:

List<? extends Number> l = new ArrayList<Integer>();
List<? extends Number> l = new ArrayList<Double>();
Run Code Online (Sandbox Code Playgroud)

如果您想要一个能够容纳类Number或其子类的任何对象的列表,请执行以下操作:

List<Number> l = new ArrayList<>();

l.add(new Integer(33));
l.add(new Double(33.3d));
Run Code Online (Sandbox Code Playgroud)

(插入的值的装箱是不必要的,但为了清楚起见..)

  • 至关重要的是,通配符意味着 List *曾经有一个类型*但*我们不再知道它是什么*。 (3认同)
  • “男孩,这比理解更难解释:)”我认为大多数事情都是如此。 (3认同)

Tes*_*st2 6

上界和无界通配符集合是不可变的。

例如,您不能执行以下操作:

List<? extends Number> myList = new ArrayList<Integer>();
myList.add(new Integer(3)); //will not compile
Run Code Online (Sandbox Code Playgroud)

编译失败,因为Java List<? extends Number>在编译时不知道List的类型。

所以上面的示例中,在编译时, myList可能是List<Double>List<Integer>List的任何亚类的Number。而且由于不能将a添加Double到a List<Integer>或反之亦然,因此编译失败。

  • “上界和无界通配符集合是不可变的”-不完全是,它们仍然可以删除元素,也可以清除:-) (2认同)

小智 6

上限泛型的问题是编译器不知道将使用的确切类型,例如:

List<? extends Number> upperBounded = new ArrayList<Integer>();
upperBounded = new ArrayList<Double>();
Run Code Online (Sandbox Code Playgroud)

upperBounded可以是整数列表,也可以是双精度列表或任何其他 Number 后代。现在想象一下,如果 Java 允许我们将 Number 的任何子类添加到该 List 中,将会发生什么。

List<? extends Number> upperBounded = new ArrayList<Integer>();
upperBounded.add(1.0); // compile-time error
Run Code Online (Sandbox Code Playgroud)

好在 Java 阻止我们这样做,因为这会引入很多错误。

这同样适用于无界泛型类型。

现在下限泛型怎么样?

List<? super Integer> lowerBounded = new ArrayList<Integer>();
lowerBounded.add(0);
Run Code Online (Sandbox Code Playgroud)

这是完全可以的,因为我们可以安全地假设我们可以将 Integers 添加到 Integer 超类的任何 List 中,并且这不会导致不一致,例如:

List<? super Integer> lowerBounded = new ArrayList<Number>();
lowerBounded.add(0);
Run Code Online (Sandbox Code Playgroud)

这里我们有一个允许整数列表或整数超类型之一的引用。Numbers 的 ArrayList 符合该定义,因此我们可以将其分配给该引用。然后我们可以向这个列表添加一个整数,这也很好,因为数字列表可以包含一个整数(因为整数是一个数字)。

这可能会令人惊讶,但您不能将任何不可分配给 Integer 的内容添加到此列表中,原因与我上面针对下限泛型所解释的原因相同。

List<? super Integer> lowerBounded = new ArrayList<Number>();
lowerBounded.add(1.0); // compile-time error
Run Code Online (Sandbox Code Playgroud)

由于编译器不知道将使用哪种确切类型的 List,因此它不允许我们添加任何可能违反泛型给出的承诺的内容。

希望有帮助。


Phi*_*nov 2

因为List<? extends Number>意味着您的变量持有一个具有扩展的具体(但未知!)类型参数l的类型值。ListNumber

您只能添加null,因为l可以保存List<MyClass>例如,MyClass扩展的类在哪里Number,但 或Integer,也不Double能将值转换为MyClass