在Java 7中使用菱形运算符

时间:2014-06-20 20:13:00

标签: java generics

在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));

代码完美无缺。这背后的原因可能是什么?

先谢谢。

2 个答案:

答案 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中的泛型是协变的,如果AB的子类型,则List[A]List[B]的子类型。但在Java中并非如此。 (Scala有一个协方差实现。在Scala中,如果B扩展A,那么List[B]扩展List[A]

String[]Object[]

的子类型

因此,ArrayList<Double>无法像您的情况一样投放到ArrayList<Number>