Почему оператор алмаза не работает для 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<>();
метод, который вы используете, ожидает карту известного типа. Алмазный синтаксис - это всего лишь сахар для стандартного синтаксиса объявления и инициализации общих классов.