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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25818287/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 08:44:37  来源:igfitidea点击:

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

javagenericsdiamond-operator

提问by Simon Kissane

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

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

   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)

它编译得很好。(我在这里以synchronizedMap为例,但对于其他Collections方法,不可修改*,synchronized*等也是如此)

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

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

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?

我尝试在 JLS 中寻找一个子句,它说这种语法是不可接受的,但我找不到。任何人都可以指点我吗?

回答by rgettman

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.

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

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

此更改是针对 Java 8 的 JEP(JDK 增强提案)101

Summary

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

概括

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

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.synchronizedMapto the diamond operator in the parameter to that call, new HashMap<>().

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

回答by David Limkys

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.

V 由 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.

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

回答by Lucas

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

这是因为您正在尝试传递new HashMap<>()Collections类的方法。这与执行以下操作不同:

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.

您正在使用的方法需要已知类型的 Map。菱形语法只是声明和初始化泛型类的标准语法的一种糖。