Frage

Der Diamant-Operator in Java 7 ermöglicht Code wie folgt aus:

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

Jedoch in Java 6.5, kann ich einfach schreiben:

List<String> list = new LinkedList();

Mein Verständnis von Typ Löschung ist, dass diese genau gleich. (Die generische wird zur Laufzeit sowieso entfernt).

Warum mit dem Diamanten überhaupt die Mühe machen? Was neue Funktionen / Typ Sicherheit macht es erlauben? Wenn es ergibt keine neue Funktionen, warum erwähnen sie es als Feature? Ist mein Verständnis dieses Konzepts fehlerhaft?

War es hilfreich?

Lösung

Das Problem mit

List<String> list = new LinkedList();

ist, dass auf der linken Seite, die Sie mit der generic Typ List<String> wo auf der rechten Seite Sie mit der raw Typ LinkedList. Raw-Typen in Java effektiv existieren nur für die Kompatibilität mit bereits Generika-Code und sollte nie in neuen Code verwendet werden, es sei denn, Sie haben absolut zu.

Nun, wenn Java Generics hatte von Anfang an und hat keine Typen, wie LinkedList, die ursprünglich erstellt wurden, bevor es Generika hatte, ist es wahrscheinlich machte es so sein könnte, dass der Konstruktor für einen generischen Typen folgert automatisch seine Art Parameter von der linken Seite der Zuordnung, wenn möglich. Aber es nicht, und es muss rohe Typen und generische Typen unterschiedlich für die Abwärtskompatibilität behandeln. Das lässt sie benötigen, um eine machen etwas anders , aber ebenso bequem, Art und Weise eine neue Instanz eines generischen Objekts zu erklären, ohne seinen Typ Parameter ... den Diamanten Operator zu wiederholen.

Soweit Ihr ursprüngliches Beispiel List<String> list = new LinkedList(), erzeugt der Compiler eine Warnung für diese Zuordnung, weil sie müssen. Bedenken Sie:

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);

existiert Generics Kompilierung-Schutz bieten gegen das Falsche zu tun. Im obigen Beispiel bedeutet die rohe Art verwenden Sie nicht diesen Schutz erhalten und werden einen Fehler zur Laufzeit bekommen. Aus diesem Grund sollten Sie nicht roh Typen verwenden.

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

Der Diamant Operator ermöglicht es jedoch, die rechte Seite der Zuweisung als eine echte generische Instanz mit den gleichen Typ Parameter wie die linke Seite definiert werden ... ohne erneut die Parameter eingeben zu müssen. Es ermöglicht Ihnen, die Sicherheit von Generika zu halten mit fast dem gleichen Aufwand wie die rohe Art verwendet wird.

Ich denke, der Schlüssel, was zu verstehen ist, dass rohe Typen (ohne <>) können nicht die gleiche wie generische Typen behandelt werden. Wenn Sie eine rohe Art erklären, Sie keine der Vorteile erhalten und geben von Generika zu überprüfen. Sie müssen auch bedenken, dass Generika ein Allzweck Teil der Java-Sprache ist ... Sie gelten nicht nur für den nicht argument Konstrukteure Collections!

Andere Tipps

Ihr Verständnis ist etwas fehlerhaft. Der Diamant-Operator ist ein nettes Feature, da Sie sich nicht wiederholen. Es macht Sinn, die Art einmal zu definieren, wenn Sie die Art erklären, aber macht einfach keinen Sinn, es auf der rechten Seite wieder zu definieren. Das DRY-Prinzip.

Nun sind alle Flaum über das Definieren von Typen zu erklären. Sie haben Recht, dass der Typ zur Laufzeit entfernt wird, aber wenn man etwas aus einer Liste mit Typdefinition abrufen möchten Sie es zurück, als die Art erhalten Sie definiert haben, wenn die Liste erklärt sonst wäre es alle spezifischen Eigenschaften verlieren und nur die Objekt verfügt außer, wenn Sie das abgerufene Objekt geworfen würde zu seiner ursprünglichen Art ist, die manchmal sehr schwierig sein kann und führen zu einer Classcast.

List<String> list = new LinkedList() Verwendung erhalten Sie rawtype Warnungen.

Diese Zeile bewirkt, dass die [ungeprüft] Warnung:

List<String> list = new LinkedList();

Also, die Frage Transformationen: warum [ungeprüft] Warnung wird nicht automatisch nur für den Fall unterdrückt, wenn neue Kollektion erstellt

Ich denke, es wäre sehr viel schwierige Aufgabe <> Feature dann hinzufügen.

UPD . Ich denke auch, dass es ein Chaos, wenn es rechtlich roh Typen zu verwenden sind ‚nur für ein paar Dinge‘

In der Theorie der Diamant Operator ermöglicht es Ihnen, durch die Einsparung wiederholte Typargumente kompaktere (und lesbar) Code zu schreiben. In der Praxis ist es nur zwei verwirrende Zeichen mehr geben Sie nichts. Warum?

  1. Kein vernünftiger Programmierer nutzt rohe Typen in neuem Code ein. So ist der Compiler einfach, dass Argumente, indem er keine Art annehmen könnte man es ihnen ableiten wollen.
  2. Der Diamant Betreiber keine Typinformationen bereitstellt, es sagt nur der Compiler „es werde in Ordnung sein“. So durch Weglassen kann nicht schaden. An jedem Ort, an dem der Diamant-Operator ist legal könnte es „geschlossen“ werden durch den Compiler.

IMHO, eine klare und einfache Art und Weise mit einer Quelle zu markieren, wie Java 7 wäre nützlicher als solche seltsamen Dinge zu erfinden. In so markierten Code könnte roher Typ ohne etwas zu verlieren verboten werden.

Btw., Ich glaube nicht, dass es mit einem Compiler-Schalter durchgeführt werden sollte. Die Java-Version einer Programmdatei ist ein Attribut der Datei, keine Option überhaupt. Mit etwas so trivial, wie

package 7 com.example;

könnte deutlich machen, (Sie etwas anspruchsvollere, die eine oder mehr Phantasie Keywords bevorzugen). Es wäre sogar erlauben Quellen geschrieben für verschiedene Java-Versionen zusammen ohne Probleme zu kompilieren. Es würde erlaubt neue Keywords Einführung (zum Beispiel „Modul“) oder einige veralteten Funktionen (mehrere nicht-öffentliche nicht-verschachtelten Klassen in einer einzigen Datei oder was auch immer) fallen, ohne eine Kompatibilität zu verlieren.

Wenn Sie List<String> list = new LinkedList(); schreiben, Compiler erzeugt eine „ungeprüft“ Warnung. Sie können es ignorieren, aber wenn man diese Warnungen ignorieren verwendet, um Sie können auch eine Warnung verpassen, dass benachrichtigt Sie über eine echte Art Sicherheitsproblem.

Also, es ist besser, einen Code zu schreiben, der keine zusätzliche Warnungen generiert, und Diamant-Operator ermöglicht es Ihnen, es in bequemer Weise ohne unnötige Wiederholungen zu tun.

sagte Alle in den anderen Antworten sind gültig, aber die Anwendungsfälle sind nicht vollständig gültig IMHO. Wenn man checkt Guava und vor allem die Sammlungen in Verbindung stehendes Material hat die gleiche getan worden mit statische Methoden. Z.B. Lists.newArrayList () , die Sie schreiben können

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

oder mit statischem Import

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

hat Guava andere sehr leistungsstarke Funktionen wie diese, und ich kann mir eigentlich nicht viel Verwendungen für die <>.

Es wäre gewesen nützlicher, wenn sie zur Herstellung des Diamanten Operator Verhalten gehen der Standard, das heißt, ist der Typ von der linken Seite des Ausdrucks inferiert oder wenn der Typ der linken Seite wurde von der rechten Seite inferiert. Letzteres ist das, was in Scala passiert.

Der Punkt für Diamant-Operator ist einfach mit der Eingabe des Codes zu reduzieren, wenn generische Typen deklariert. Es hat keine Auswirkungen auf die Laufzeit auch immer.

Der einzige Unterschied, wenn Sie in Java angeben 5 und 6,

List<String> list = new ArrayList();

ist, dass Sie @SuppressWarnings("unchecked") zum list angeben müssen (ansonsten werden Sie eine ungeprüfte Guss Warnung erhalten). Mein Verständnis ist, dass Diamant-Operator versucht, die Entwicklung zu erleichtern. Es hat nichts zu Laufzeitausführung von Generika überhaupt zu tun.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top