В чем смысл алмазного оператора в Java 7?


оператор diamond в java 7 позволяет использовать следующий код:

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

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

List<String> list = new LinkedList();

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

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

7 411

7 ответов:

вопрос с

List<String> list = new LinkedList();

это на левой стороне, вы используете generic тип 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);

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

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

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

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

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

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

С помощью List<String> list = new LinkedList() вы получите предупреждения rawtype.

эта строка вызывает [unchecked] предупреждение:

List<String> list = new LinkedList();

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

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

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

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

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

IMHO, имея ясный и простой способ пометить источник как Java 7 было бы более полезно, чем изобретать такие странные вещи. В таком маркированном коде необработанные типы могут быть запрещены без потери чего-либо.

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

package 7 com.example;

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

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

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

все сказанное в других ответах допустимо, но варианты использования не являются полностью допустимыми IMHO. Если один проверяет гуавы и особенно связанные с коллекциями вещи, то же самое было сделано со статическими методами. Е. Г. списки.newArrayList () что позволяет вам писать

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

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

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

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

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

пункт для оператора Диаманта просто уменьшить печатать кода объявляя родовые типы. Это не имеет никакого влияния на время выполнения вообще.

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

List<String> list = new ArrayList();

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