Вопрос

Алмазный оператор в Java 7 позволяет коду как следующее:

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

Однако в Java 5/6 я могу просто написать:

List<String> list = new LinkedList();

Мое понимание типового стирания в том, что они точно такие же. (Универсальный удален во время выполнения в любом случае).

Зачем вообще беспокоиться с бриллиантом? Какую новую функциональность / тип безопасности это разрешено? Если это не дает никакой новой функциональности, почему они упоминают об этом как функция? Является ли мое понимание этой концепции недостаточно?

Это было полезно?

Решение

Проблема с

List<String> list = new LinkedList();

Это на левой стороне, вы используете розыгрыш тип List<String> где на правой стороне вы используете сырой тип LinkedList. Отказ Сырые типы в Java эффективно существуют только для совместимости с кодом предварительного универсала и никогда не должны использоваться в новом коде, если вы не должны быть.

Теперь, если у 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);

Дебитки существуют, чтобы обеспечить защиту времени компиляции против выполнения неправильной вещи. В приведенном выше примере, используя SHAR-тип означает, что вы не получаете эту защиту и получите ошибку во время выполнения. Вот почему вы не должны использовать сырье.

// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);

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

Я думаю, что ключевая вещь, которую нужно понять, это то, что сырье (без <>) нельзя рассматривать так же, как общие типы. Когда вы объявите необработанный тип, вы не получаете никакие преимущества и тип проверки универсальных. Вы также должны иметь в виду, что Generics - это общее назначение частью языка Java... они не просто применимы к конструкторам No-Arg Collection!

Другие советы

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

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

С использованием List<String> list = new LinkedList() Получу вам предупреждения Rawtype.

Эта линия вызывает [не проверяемое] предупреждение:

List<String> list = new LinkedList();

Итак, в вопросе трансформируется: почему [не проверяемое] предупреждение не подавляется автоматически только для случая, когда создается новая коллекция?

Я думаю, что это было бы намного сложнее задание, а затем добавлять <> характерная черта.

Уполномоченный: Я также думаю, что будет беспорядок, если бы он был на законных основаниях использовать сырье, просто для нескольких вещей ».

Теоретически, оператор алмаза позволяет вам писать более компактный (и читаемый) код, сохраняя повторные аргументы типа. На практике это всего лишь два запутанных символа больше ничего не дающих вам. Почему?

  1. Ни один здравомыслящий программист не использует сырье в новом коде. Таким образом, компилятор мог просто предположить, что, написав никаких аргументов типа, вы хотите, чтобы его вывод.
  2. Алмазный оператор предоставляет никакой информации, она просто говорит, что компилятор: «Это будет хорошо». Так что, опуская его, вы не можете не причинить вреда. В любом месте, где оператор алмаза является законным, он может быть «выведен» компилятором.

ИМХО, прозрачный и простой способ отметить источник, так как Java 7 будет более полезным, чем изобретать такие странные вещи. При настолько отмеченным кодом необработанные типы могут быть запрещены, не теряя ничего.

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

package 7 com.example;

может сделать это понятно (вы можете предпочесть что-то более сложное, включая одно или несколько причудливых ключевых слов). Это даже позволило бы собрать источники, написанные для разных версий Java вместе без каких-либо проблем. Это позволило бы представить новые ключевые слова (например, «модуль») или бросать некоторые устаревшие функции (несколько непубличных не вложенных классов в одном файле или Whatsoever), не теряя любую совместимость.

Когда вы пишете List<String> list = new LinkedList();, Компилятор производит «незаменимое» предупреждение. Вы можете игнорировать это, но если вы использовали для игнорирования этих предупреждений, вы также можете пропустить предупреждение, которое уведомляет вас о проблеме безопасности реального типа.

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

Все сказанные в других ответах действительны, но случаи использования не являются полностью действительными IMHO. Если кто-то проверяет Гуава И особенно коллекции, связанные с ними, то же самое было сделано со статическими методами. Например Lists.newarrayList () который позволяет писать

List<String> names = Lists.newArrayList();

или со статическим импортом

import static com.google.common.collect.Lists.*;
...
List<String> names = newArrayList();
List<String> names = newArrayList("one", "two", "three");

Guava имеет другие очень мощные функции, такие как это, и я на самом деле не могу придумать много использования для <>.

Было бы более полезно, если бы они пошли за создание поведения оператора алмаза по умолчанию, то есть тип выводится с левой стороны выражения или если тип левой стороны был выведен с правой стороны. Последнее это происходит в Scala.

Точка для оператора Diamond - просто уменьшить набрав кода при объявлении универсальных типов. Это не влияет на время выполнения.

Единственная разница, если вы укажете в Java 5 и 6,

List<String> list = new ArrayList();

это то, что вы должны указать @SuppressWarnings("unchecked") к тому list (в противном случае вы получите незаменимое предъявление предупреждение). Мое понимание заключается в том, что оператор алмаза пытается облегчить развитие. Это не имеет ничего общего, чтобы вообще делать время выполнения дженериков.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top