Почему оператор алмаза используется для вывода типа в Java 7?

List<String> list = new ArrayList(); приведет к предупреждению компилятора.

Однако следующий пример компилируется без предупреждения: List<String> list = new ArrayList<>();

Мне любопытно, почему вообще требуется внедрение алмазного оператора. Почему бы просто не вводить тип в конструкторе, если аргумент типа отсутствует (как это уже сделано для статических методов в java и используется библиотеками коллекции, такими как google guava)

РЕДАКТИРОВАТЬ. Используя миллимозный ответ в качестве отправной точки, я посмотрел, что такое стирание на самом деле, и оно не просто удаляет всю информацию о типе. Компилятор на самом деле немного больше (скопирован из официальный документ):

  • Замените все параметры типа в родовых типах своими границами или объектом, если параметры типа не ограничены. Таким образом, полученный байт-код содержит только обычные классы, интерфейсы и методы.
  • Вставьте тип при необходимости, чтобы сохранить безопасность типа.
  • Создание мостовых методов для сохранения полиморфизма в расширенных общих типах.

Ответ 1

Окончательный ответ должен был исходить от кого-то, кто разработал эту функцию, но я предполагаю, что это отличает это от использования необработанных типов, которые заставляют компилятор сделать что-то совсем другое ради совместимости. Выражение с сырым типом в нем обрабатывается тонко по-разному, чем одно, которое включает в себя дженерики, пример найден в этом вопросе SO: Общие винты с несвязанной коллекцией

Ответ 2

Разработчики Java очень стараются избегать изменения поведения существующих программ. List<String> list = new ArrayList(); выполняет компиляцию и создает необработанный ArrayList. Если к нему применен вывод типа, результат будет ArrayList<String>, изменив его поведение и, возможно, вызовет ошибки времени выполнения в другом месте программы.

=============================================== =============================

После дальнейшего рассмотрения и комментария @millimoose, я вижу, что изменения в поведении будут локальными для инициализатора и будут обнаружены во время компиляции. Рассмотрим следующую программу:

import java.util.ArrayList;
import java.util.List;


public class Test {
  public static void main(String[] args) throws Exception {
    List<Integer> integers = new ArrayList<Integer>();
    integers.add(Integer.valueOf(3));
    integers.add(Integer.valueOf(4));
    List<String> list = new ArrayList(integers);
    System.out.println(list);
  }
}

Без вывода типа он запускает и печатает [3, 4], несмотря на нежелательную ситуацию List<String>, которая содержит ссылки Integer.

С типом вывода он не будет компилироваться, потому что ArrayList(Collection<? extends E> c) не позволяет использовать аргумент List<Integer> в качестве аргумента при создании ArrayList<String>.

Ответ 3

Полный синтаксис, требуемый компилятором java 5 и 6, следующий:

List<String> list = new ArrayList<String>();

Они решили упростить синтаксис для нас и позволить не писать параметры одного и того же типа с обеих сторон оператора присваивания. Однако оператор <> по-прежнему должен убедиться, что вы понимаете, что вы делаете. Написав new ArrayList<>(), вы говорите: "Я понимаю, что создаю экземпляр родового типа, а общий параметр - как один, который я указал в левой части задания".

Ответ 4

Это часть улучшения Java Generics в Java 7.
Прежде чем вам пришлось бы писать

final List<String> list = new ArrayList<String>();

Теперь вы можете написать

final List<String> list = new ArrayList<>();

Что эквивалентно - компилятор будет работать для вас. Это не то же самое, что

final List list = new ArrayList();

Что такое нетипизированный List.

Ответ 5

Интересны случаи, когда вызов конструктора с алмазом и как rawtype успешно компилируется, но создает другой код. Такие примеры возможны при смешивании с функцией перегрузки метода. IIRC, был пример где-то в списке рассылки монеты OpenJDK (нет, я не собираюсь его искать).

Было неприемлемо, чтобы точно такой же код успешно появился на Java SE 6 и Java SE 7, но при этом получал разные результаты.

За свои деньги я бы опустил бриллиант и дал предупреждение (рассматриваем как ошибку), если бы другой код был создан алгоритмом вывода, выбранным в 7 (по сути, таким же, как для вывода метода общего типа из J2SE 5.0). Если вы написали такой код, вероятно, неясно, если он скомпилируется или нет.

Ответ 6

Если ваш проект построен на maven, добавьте ниже в pom.xml под тегом. Он отлично работает.. <plugins>    <plugin>      <groupId>org.apache.maven.plugins</groupId>      <artifactId>maven-compiler-plugin</artifactId>      <version>3.7.0</version>      <configuration>        <source>1.8</source>        <target>1.8</target>      </configuration>    </plugin> </plugins>