在Java 7之前,下面的语法用于创建ArrayList,
ArrayList<Integer> ints = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7));
但是从Java 7开始我们可以省略构造函数中的泛型类型,即
ArrayList<Integer> ints = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7));
但是当我尝试做类似的事情时,
ArrayList<Number> nums = new ArrayList<>(Arrays.asList(1,2,3,4,4,5.5,6.6,7.7));
我收到错误,但是当我在右侧提到通用类型时,即
ArrayList<Number> nums = new ArrayList<Number>(Arrays.asList(1,2,3,4,5.5,6.6,7.7));
代码完美无缺。这背后的原因可能是什么?
先谢谢。
答案 0 :(得分:4)
Arrays.asList
是一种通用方法,因此从技术上讲,它可以调用为:
Arrays.<Number> asList(1, 2, 3);
即使在Java 7之前,当左侧知道时,该语言可以做一些有限的推断以消除这种情况,如
final List<Number> nums = Arrays.asList(1, 2, 3);
看起来你偶然发现了两种类型的推理无法成功组合的边缘情况,其中钻石推理和通用方法推理不相处。如果你要深入研究它,我肯定the JLS sheds more light on this。
答案 1 :(得分:3)
Java Generics是Invariant,而Arrays是Covariant。
如果Java中的泛型是协变的,如果A
是B
的子类型,则List[A]
是List[B]
的子类型。但在Java中并非如此。 (Scala有一个协方差实现。在Scala中,如果B
扩展A
,那么List[B]
扩展List[A]
)
但String[]
是Object[]
因此,ArrayList<Double>
无法像您的情况一样投放到ArrayList<Number>
。