Почему оператор алмаза не работает для java.util.Collections методов в Java 7?

В 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, unmodifiable *, synchronized * и т.д.)

Но почему алмазный оператор не работает, как я ожидал бы здесь? Поскольку Collections.synchronizedMap() объявляется как:

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

Мне кажется, что параметры типа вызова конструктора должны быть такими же, как и для объявления поля, и компилятор должен иметь возможность выводить на него построенные параметры типа класса.

Я попытался найти предложение в JLS, в котором говорится, что этот синтаксис неприемлем, но я не могу его найти. Может ли кто-нибудь указать мне на это?

Ответы

Ответ 1

Это не удается с ошибкой вашего компилятора в Java 7, но успешно компилируется в Java 8. Короче говоря, вывод типа компилятора не выявил правильные выводимые типы в Java 7, но лучший вывод типа указывает на правильные типы в Java 8.

Это изменение было JEP (JDK Enhancement Proposal) 101 для Java 8.

Резюме

Плавно расширьте область применения метода-вывода для поддержки (i) вывода в контексте метода и (ii) вывода в цепочке вызовов.

Java 8 позволяет выводить типы посредством нескольких вызовов методов с параметрами и цепочкой вызовов метода. Теперь он может определить с левой стороны задания <String, Object> по вызову Collections.synchronizedMap оператору алмаза в параметре для этого вызова new HashMap<>().

Ответ 2

Когда метод объявлен как

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

Генераторы задаются параметрами.

скажет, что я делаю это:

public <V> V returnV(V v);

Тогда я называю это:

returnV("myString")

V отключается myString.

когда вы даете

new HashMap<>()

Тогда нет никаких дженериков, поэтому компилятор угадывает вас:

new HashMap<Object, Object>()

И вы получите

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

И это ошибка и несовместимые типы.

Ответ 3

Это потому, что вы пытаетесь передать new HashMap<>() методу класса Collections. Это отличается от выполнения:

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

метод, который вы используете, ожидает карту известного типа. Алмазный синтаксис - это всего лишь сахар для стандартного синтаксиса объявления и инициализации общих классов.