Проблема с
List<String> list = new LinkedList();
заключается в том, что с левой стороны вы используете общий тип List<String>
, где с правой стороны вы используете raw тип LinkedList
. Необработанные типы в Java эффективно существуют только для совместимости с кодом pre-generics и никогда не должны использоваться в новом коде, если вам не обязательно.
Теперь, если у Java были генерики с самого начала и не имели типов , такие как LinkedList
, которые изначально были созданы до того, как появились дженерики, вероятно, это могло бы сделать так, чтобы конструктор для генерического типа автоматически обнаруживал параметры своего типа с левой стороны задания, если это было возможно. Но это не так, и он должен относиться к сырым типам и общим типам по-разному для обратной совместимости. Это оставляет им необходимость сделать немного отличающимся , но не менее удобным, способом объявления нового экземпляра родового объекта без необходимости повторять его параметры типа ... алмазный оператор.
Что касается вашего исходного примера List<String> list = new LinkedList()
, компилятор генерирует предупреждение для этого назначения, потому что он должен. Рассмотрим это:
List<String> strings = ... // some list that contains some strings
// Totally legal since you used the raw type and lost all type checking!
List<Integer> integers = new LinkedList(strings);
Существуют общие возможности для обеспечения защиты во время компиляции от неправильного действия. В приведенном выше примере использование исходного типа означает, что вы не получите эту защиту и получите ошибку во время выполнения. Вот почему вы не должны использовать необработанные типы.
// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);
Однако оператор алмаза позволяет определить правую часть задания как истинный общий экземпляр с параметрами того же типа, что и левый стороне ... без необходимости повторного ввода этих параметров. Это позволяет сохранить безопасность дженериков с помощью почти с теми же усилиями, что и с использованием необработанного типа.
Я думаю, что ключевым моментом для понимания является то, что необработанные типы (без <>
) нельзя рассматривать так же, как общие типы. Когда вы объявляете необработанный тип, вы не получаете никаких преимуществ и типов проверки дженериков. Вы также должны иметь в виду, что дженерики являются частью общего назначения языка Java ... они не просто применяются к конструкторам no-arg из Collection
s!