web-dev-qa-db-de.com

Wozu dient der Diamantoperator (<>) in Java 7?

Der Raute-Operator in Java 7 erlaubt Code wie den folgenden:

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

In Java 5/6 kann ich jedoch einfach schreiben:

List<String> list = new LinkedList();

Mein Verständnis der Typ-Löschung ist, dass diese genau gleich sind. (Das Generikum wird ohnehin zur Laufzeit entfernt).

Warum sollte man sich überhaupt mit dem Diamanten beschäftigen? Welche neue Funktionalität/Typensicherheit ermöglicht es? Wenn es keine neuen Funktionen gibt, warum wird es dann als Feature erwähnt? Ist mein Verständnis dieses Konzepts fehlerhaft?

434
tofarr

Ihr Verständnis ist leicht fehlerhaft. Der Diamantoperator ist eine nette Funktion, da Sie sich nicht wiederholen müssen. Es ist sinnvoll, den Typ einmal zu definieren, wenn Sie ihn deklarieren, aber es ist einfach nicht sinnvoll, ihn auf der rechten Seite erneut zu definieren. Das DRY Prinzip.

Erklären Sie nun die Unklarheiten beim Definieren von Typen. Sie haben Recht, dass der Typ zur Laufzeit entfernt wird, aber wenn Sie etwas aus einer Liste mit Typdefinition abrufen möchten, erhalten Sie es als den Typ zurück, den Sie beim Deklarieren der Liste definiert haben. Andernfalls würden alle spezifischen Funktionen verloren gehen und nur die Objektfunktionen, außer wenn Sie das abgerufene Objekt in den ursprünglichen Typ umwandeln. Dies kann manchmal sehr schwierig sein und zu einer ClassCastException führen.

Wenn Sie List<String> list = new LinkedList() verwenden, erhalten Sie Warnungen zu Rohtypen.

34

Diese Zeile verursacht die [ungeprüfte] Warnung:

List<String> list = new LinkedList();

Die Frage wandelt sich also: Warum wird die [nicht aktivierte] Warnung nicht automatisch nur für den Fall unterdrückt, wenn eine neue Sammlung erstellt wird?

Ich denke, es wäre eine viel schwierigere Aufgabe als das Hinzufügen von <> Feature.

UPD : Ich denke auch, dass es ein Durcheinander geben würde, wenn es legal wäre, Rohtypen "nur für ein paar Dinge" zu verwenden.

16
Roman

Theoretisch können Sie mit dem Diamond-Operator kompakter (und lesbarer) Code schreiben, indem Sie Argumente mit wiederholtem Typ speichern. In der Praxis sind es nur zwei verwirrende Zeichen mehr, die Ihnen nichts bringen. Warum?

  1. Kein vernünftiger Programmierer verwendet Rohtypen in neuem Code. Der Compiler könnte also einfach davon ausgehen, dass er keine Typargumente schreiben möchte, um sie abzuleiten.
  2. Der Diamantoperator liefert keine Typinformationen, er sagt nur dem Compiler, "es wird gut". Wenn Sie es also weglassen, können Sie nichts anrichten. An jedem Ort, an dem der Diamantoperator legal ist, kann er vom Compiler "gefolgert" werden.

Meiner Meinung nach wäre eine klare und einfache Möglichkeit, eine Quelle als Java 7) zu kennzeichnen, sinnvoller, als solche seltsamen Dinge zu erfinden. In so gekennzeichnetem Code könnten Rohtypen verboten werden, ohne etwas zu verlieren.

Übrigens denke ich nicht, dass es mit einem Compile-Schalter getan werden sollte. Die Java Version einer Programmdatei ist ein Attribut der Datei, keine Option. Verwenden Sie etwas so Triviales wie

package 7 com.example;

könnte es klarstellen (vielleicht bevorzugen Sie etwas Anspruchsvolleres, einschließlich eines oder mehrerer ausgefallener Schlüsselwörter). Es würde sogar erlauben, Quellen, die für verschiedene Java) - Versionen geschrieben wurden, problemlos zusammen zu kompilieren. Es würde das Einfügen neuer Schlüsselwörter (z. B. "Modul") oder das Löschen einiger veralteter Funktionen (mehrere nicht öffentliche nicht) ermöglichen -verschachtelte Klassen in einer einzelnen Datei (oder was auch immer), ohne die Kompatibilität zu verlieren.

13
maaartinus

Wenn Sie List<String> list = new LinkedList(); schreiben, gibt der Compiler eine "ungeprüfte" Warnung aus. Sie können es ignorieren, aber wenn Sie diese Warnungen früher ignoriert haben, wird möglicherweise auch eine Warnung übersehen, die Sie über ein echtes Sicherheitsproblem informiert.

Es ist daher besser, einen Code zu schreiben, der keine zusätzlichen Warnungen generiert, und der Diamantoperator ermöglicht es Ihnen, dies auf bequeme Weise ohne unnötige Wiederholung zu tun.

8
axtavt

Alle in den anderen Antworten genannten sind gültig, aber die Anwendungsfälle sind meiner Meinung nach nicht vollständig gültig. Wenn man Guava und vor allem die sammlungsbezogenen Sachen auscheckt, ist dasselbe mit statischen Methoden gemacht worden. Z.B. Lists.newArrayList () Damit können Sie schreiben

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

Guava hat andere sehr mächtige Funktionen wie diese und ich kann mir nicht vorstellen, wie viel für das <> verwendet werden kann.

Es wäre sinnvoller gewesen, das Verhalten des Diamantoperators als Standard festzulegen, d. H., Der Typ wird von der linken Seite des Ausdrucks abgeleitet, oder der Typ der linken Seite wurde von der rechten Seite abgeleitet. Letzteres passiert in Scala.

4
allprog

Der Punkt für Diamantoperatoren ist einfach, die Code-Typisierung zu reduzieren, wenn generische Typen deklariert werden. Es hat keinerlei Auswirkungen auf die Laufzeit.

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

List<String> list = new ArrayList();

ist, dass Sie @SuppressWarnings("unchecked") für list angeben müssen (andernfalls erhalten Sie eine ungeprüfte Cast-Warnung). Ich verstehe, dass der Diamantoperator versucht, die Entwicklung zu vereinfachen. Es hat überhaupt nichts mit der Laufzeitausführung von Generika zu tun.

3
Buhake Sindi