ArrayList,带有Java中的泛型声明

use*_*065 5 java generics collections

以下代码给出了该行的错误 l.add

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

并强迫我把它写成 l.add(1, null);

为什么会这样?

rge*_*man 12

通过变量上的通配符l,编译器不知道(或关心)类型参数的哪个Number(或Number自身)子类.它可能是一个ArrayList<Double>或一个ArrayList<BigInteger>.它不能保证传入的类型的安全性add,并且由于类型擦除,JVM也无法捕获类型不匹配.因此,编译器通过禁止此类调用来保留类型安全性,add除非值为null,可以是任何类型.

add编译,您必须声明l为:

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

或者您可以删除通配符:

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

  • 助记符"PECS"有助于记住使用哪个.请参见http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs. (2认同)

Kon*_*kov 7

它一定要是:

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

请注意<? super Integer>声明.它被称为上限通配符.

它有什么作用?

它限制的元素的运行时类型ArrayList是父类中的一种Integer,例如Integer,Number或者Object,这意味着你将能够分配l到:

  • new ArrayList<Integer>
  • new ArrayList<Number>
  • new ArrayList<Object>

在这三种情况下,语句l.add(1)完全有效,因此没有编译时错误.

更多信息: