2014-10-08 88 views
2

我想使用ArrayList的构造函数:ArrayList的类型推断

ArrayList(Collection<? extends E> c) 

如下。

List<Integer> li = new ArrayList<>(); 

List<Number> ln = new ArrayList<>(li); // won't compile.. Type mismatch: cannot convert from ArrayList<Integer> to List<Number> 

我不明白编译器错误。

但是,以下编译正常。

List<Number> ln = new ArrayList<Number>(li); 

我在想什么?使用java 7

+0

有人可以在Java8上试试这个吗?也许目标类型推断已被改进? – Thilo 2014-10-08 02:38:58

回答

0

这是“钻石操作员”的限制。

List<Number> ln = new ArrayList<>(li); 

被扩大到

List<Number> ln = new ArrayList<Integer>(li); 

不编译。

您可以通过更明确的解决这个问题:

List<Number> ln = new ArrayList<Number>(li); 
+1

这种扩张究竟如何发生?李是一个构造函数的参数。 – user2953113 2014-10-08 02:31:11

+0

@ user2953113:我不确定...但是'Integer'部分必须来自'li'(它必须与构造函数签名相匹配,可用选项是'Integer','Number','' Object','Serializable','Comparable'。我想语言规范只是使用对象类型本身)。 – Thilo 2014-10-08 02:33:44

+0

了解扩展如何发生。构造函数中的E()链接到ArrayList 中的E.在li的情况下,E变为Integer,并且ArrayList 变成ArrayList 。 – user2953113 2014-10-08 03:06:30

1

的问题是Java创建ArrayList类型<整数>的新对象。由于Integer与Number不完全相同,因此不能将其分配给List <Number>类型的变量。您必须使用通配符,像这样:

List<Integer> li = new ArrayList<>(); 
List<? extends Number> ln = new ArrayList<>(li); 

这允许泛型类型整数,它扩展号码的清单,被分配到类型列表的变量<数>。在这里寻找更多的信息:http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html

+1

java如何创建一个ArrayList ?这个逻辑是否记录在某个地方? – user2953113 2014-10-08 02:35:30

+0

我不确定你在问什么。如果您问为什么Java选择创建ArrayList 而不是ArrayList ,这是因为li的类型是ArrayList ,并且该语言从li的类型推断出该类型。如果li的类型是List <?扩展Number>,那么你就可以完成任务。 – user2503846 2014-10-08 02:45:02

+0

我应该补充说,你可以在构造函数的签名中看到这个:ArrayList(Collection c)。在这种情况下,E来自li的通用类型。当li是List <?扩展Number>,E就是Number。 – user2503846 2014-10-08 02:47:18