Why does the diamond operator not work for java.util.Collections methods in Java 7?

↘锁芯ラ 提交于 2019-11-28 07:16:14

问题


In Java 1.7.0_55, if I write this field declaration, I get a compilation error ("incompatible types"):

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

If I change that to read:

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

It compiles fine. (I'm using synchronizedMap as an example here, but the same is true for other Collections methods, unmodifiable*, synchronized*, etc)

But why does the diamond operator not work as I would expect here? Since Collections.synchronizedMap() is declared as:

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

It would seem to me that the type parameters of the constructor invocation must be the same as those of the field declaration, and the compiler should be able to infer the constructed class type parameters based on that.

I tried looking for a clause in the JLS which says this syntax is unacceptable, but I can't find one. Can anyone point me to it?


回答1:


This fails with your compiler error in Java 7, but it compiles successfully in Java 8. In short, the compiler's type inference did not catch the proper inferred types in Java 7, but the better type inference infers the proper types in Java 8.

This change was JEP (JDK Enhancement Proposal) 101 for Java 8.

Summary

Smoothly expand the scope of method type-inference to support (i) inference in method context and (ii) inference in chained calls.

Java 8 is able to infer types through multiple method calls with parameters and method call chaining. It can now determine from the left side of the assignment <String, Object> through the call to Collections.synchronizedMap to the diamond operator in the parameter to that call, new HashMap<>().




回答2:


When a method is declared like this

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

The genrecis are supplied by the parameters.

lets say i do this:

public <V> V returnV(V v);

Then i call it :

returnV("myString")

V is detrmind by myString.

when you give

new HashMap<>()

Then there are no generics so the compiler guesses you ment:

new HashMap<Object, Object>()

And so you get

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

And that is and incompatible types error.




回答3:


It's because you are trying to pass new HashMap<>() to method of Collections class. This is different than doing:

Map <String, Integer> map = new HashMap<>();

method you are using expects the Map of known type. Diamond syntax is just a sugar to standard syntax of declaring and initializing generic classes.



来源:https://stackoverflow.com/questions/25818287/why-does-the-diamond-operator-not-work-for-java-util-collections-methods-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!