为什么菱形运算符不适用于Java 7中的java.util.Collections方法?

时间:2014-09-12 23:24:54

标签: java generics diamond-operator

在Java 1.7.0_55中,如果我写这个字段声明,我会收到编译错误(“不兼容的类型”):

   private final Map<String,Object> myMap =
       Collections.synchronizedMap(new HashMap<>());

如果我将其改为:

   private final Map<String,Object> myMap =
       Collections.synchronizedMap(new HashMap<String,Object>());

编译好。 (我在这里使用synchronizedMap作为示例,但其他集合方法也是如此,不可修改*,同步*等)

但是为什么钻石操作员不像我期望的那样工作?由于Collections.synchronizedMap()声明为:

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {

在我看来,构造函数调用的类型参数必须与字段声明的类型参数相同,编译器应该能够根据它推断构造的类类型参数。

我试图在JLS中寻找一个条款,说这种语法是不可接受的,但我找不到。有人能指出我吗?

3 个答案:

答案 0 :(得分:10)

这在Java 7中因编译错误而失败,但它在Java 8中成功编译。简而言之,编译器的类型推断没有捕获Java 7中正确的推断类型,但更好的类型推断推断出Java 8中适当的类型。

此更改为JEP (JDK Enhancement Proposal) 101 for Java 8

  

<强>摘要

     

平滑地扩展方法类型推断的范围,以支持(i)方法上下文中的推理和(ii)链式调用中的推理。

Java 8能够通过多个方法调用使用参数和方法调用链来推断类型。现在,它可以从作业<String, Object>的左侧通过调用Collections.synchronizedMap到该调用的参数new HashMap<>()中的菱形运算符来确定。

答案 1 :(得分:3)

当声明方法时

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {

genrecis由参数提供。

让我这样说:

public <V> V returnV(V v);

然后我称之为:

returnV("myString")

V是myString的detrmind。

当你提供

new HashMap<>()

然后没有泛型,所以编译器猜测你:

new HashMap<Object, Object>()

所以你得到了

private final Map<String,Object> myMap =
   Collections.synchronizedMap(new HashMap<Object,Object>());

那就是和不兼容的类型错误。

答案 2 :(得分:0)

这是因为您试图将new HashMap<>()传递给Collections类的方法。这不同于:

Map <String, Integer> map = new HashMap<>();
您正在使用的

方法需要已知类型的Map。 Diamond语法只是声明和初始化泛型类的标准语法的糖。