Java 7中使用钻石操作符

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

代码运行正常,可能的原因是什么呢?谢谢。

我无法从JLS中提取在Java 7和8之间更改以支持此操作的特定段落,因此这是一个评论,但如果我没记错的话,Java 8扩展了可以执行的推断类型,我相信通过允许搜索超类型,并/或考虑其他上下文。您的第三个代码片段在Java 8中编译时没有任何问题。 - awksp
2个回答

4

Arrays.asList是一个泛型方法,因此在技术上,它可以被调用为:

Arrays.<Number> asList(1, 2, 3);

即使在Java 7之前,当左侧已知时,该语言也可以进行一些有限的推断来消除此类情况,例如:
final List<Number> nums = Arrays.asList(1, 2, 3);

看起来你遇到了一个边缘情况,在这种情况下,两种类型的推断无法成功地结合在一起,菱形推断和通用方法推断不兼容。如果你深入挖掘的话,我相信JLS会更详细地解释这个问题。

3

Java泛型是不变的,而数组是协变的。

如果Java中的泛型是协变的,那么如果AB的子类型,则List[A]List[B]的子类型。但在Java中并非如此。(Scala有一个协变实现。在Scala中,如果B扩展了A,则List[B]扩展了List[A]

但是String[]Object[]的子类型。

因此,ArrayList<Double>不能像您的情况一样转换为ArrayList<Number>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接