1. Initialisierung mit doppelter Klammer
Die Initialisierung mit doppelten Klammern (
im Folgenden als Initialisierung mit doppelten Klammern bezeichnet ) ist ein Java-Tool zum gleichzeitigen Erstellen von Sammlungen wie Listen, Mengen und Karten mit deren Deklaration.
Wenn Sie Listen mit festen Elementen benötigen, z. B. eine Liste unterstützter Produkte oder Währungen, verbessert die Deklaration der Liste gleichzeitig mit der Initialisierung die Lesbarkeit des Codes. Aus diesem Grund erfreut sich die Initialisierung mit doppelten Klammern immer größerer Beliebtheit, da es keine anderen Standardmethoden zum Erstellen von Sammlungen mit gleichzeitiger Initialisierung im Code gibt. Leider unterstützt Java im Gegensatz zu anderen Programmiersprachen keine Sammlungen von Literalen. Aufgrund dieser Einschränkung zwingt uns das Erstellen einer unmodifiableList auch nur
mit einer kleinen Anzahl von Elementen dazu, viele Codezeilen in Form wiederholter Aufrufe zu schreiben,
add()
um die gewünschten Elemente mit abschließendem Wrapping hinzuzufügen:
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(3);
list.add(5);
list.add(7);
List<Integer> unmodifiableList = Collections.unmodifiableList(list);
Dies ist eine unnötig redundante Beschreibung, die vereinfacht werden könnte. Lassen Sie uns statische Listen auf eine für uns bequeme Weise füllen, nämlich direkt in statischen Blöcken während der Initialisierung. Dabei
Double brace
hilft uns die Initialisierung, sodass wir alles in eine Zeile schreiben können:
List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>() {{
add(2);
add(3);
add(5);
}});
Ebenso
Double brace
hilft uns die Initialisierung dabei, Werte einzugeben und
HashMap
:
Map<Integer, String> intToString = new HashMap<Integer, String>(){{
put(1, "one");
put(2, "two");
put(3, "three");
}};
Das sieht alles so elegant aus, hat aber seine Nachteile, die die Initialisierung mit doppelten Klammern zu einem Anti-Muster machen. Wir werden sie uns im nächsten Kapitel genauer ansehen.
Vor- und Nachteile der Initialisierung mit doppelter Klammer.
Double
Bei der Klammerinitialisierung wird eine anonyme innere Klasse erstellt . Was jedoch zunächst an der Oberfläche verborgen bleibt,
Double brace
wird durch die Initialisierung bei jeder Verwendung einer Klasse mit einer weiteren Initialisierung ihrer Instanz erstellt. Darüber hinaus wird ein versteckter Verweis auf diese private Klasse verwendet, was zu möglichen Speicherlecks führen kann. Sie können den Ghost-Operator auch nicht für Generika verwenden (Diamond-Operator < >), da wir nicht auf das Innere einer anonymen Klasse zugreifen können.
(Vom Übersetzer: Noch einmal ausführlicher:
Nach der ersten { wird eine interne anonyme Klasse erstellt, nach der zweiten { erfolgt die Initialisierung beim Erstellen einer Instanz der Klasse, in der wir Zugriff auf die Felder und Methoden der externen ( relativ zur anonymen) Klasse.) |
Vorteile:
- Zeilen im Code reduzieren
- Erstellung und Initialisierung in einem Ausdruck.
Nachteile:
- Erstellen einer anonymen Klasse, die vor Ihnen verborgen bleibt.
- Das kostet uns bei jeder Nutzung zusätzliche Kosten für die Instanz.
- Jedes Mal wird ein versteckter Verweis darauf erstellt, was zu Speicherverlusten führen kann.
Urteil: Aufgrund der oben genannten Nachteile und der Existenz von Alternativen zur doppelten Klammer gilt die Initialisierung in der Java-Welt als Anti-Pattern.
Alternativen zur Initialisierung mit doppelten Klammern in Java
Die gute Nachricht ist, dass es in Java andere Möglichkeiten gibt, dieselben Ziele zu erreichen. Wir können die Erstellung und Initialisierung einer ArrayList mithilfe des Copy-Konstruktors aus der Collection-Klasse in einer Codezeile implementieren, wie unten gezeigt:
List<Integer> list = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(2, 3, 5)));
Arrays.asList()
gibt uns eine Liste fester Länge zurück, die an
ArrayList
den Kopierkonstruktor übergeben wird. Beachten Sie den Unterschied zwischen Listen fester Länge, die von
Arrays.asList()
und zurückgegeben werden
Collections.unmodifiableList()
: Sie können keine Elemente
ArrayList
von - hinzufügen oder entfernen, aber Sie können ein Element anhand des Index ändern , indem
set()
Sie verwenden, was bei einer von zurückgegebenen Liste nicht möglich ist
Collections.unmodifiableList()
. Wenn Sie eine kleine Liste erhalten möchten, ist dies die beste Möglichkeit, obwohl sie für andere Sammlungen weniger transparent ist , sodass Sie sie vor der Erstellung von -a
Set
erstellen müssen . Dies ist jedoch immer noch besser als die Initialisierung mit doppelten Klammern, da in diesem Fall nicht bei jeder Verwendung eine zusätzliche interne anonyme Klasse erstellt wird. Wenn Sie Java 8 ausführen, steht Ihnen eine andere alternative Methode zur Verfügung. Die JDK 8 Stream API hilft Ihnen beim Erstellen kleiner Sammlungen, indem Ausgabemethoden in einer Sammlung kombiniert werden :
List
Set
Stream Factory
List
List<String> list = Collections.unmodifiableList(Stream.of("abc", "bcd", "cde").collect(toList()));
Set
Sie können stattdessen
Collectors.toSet()
die folgende Methode verwenden
Collectors.toList()
:
Set<String> set = Collections.unmodifiableSet(Stream.of("abc", "bcd", "cde").collect(toSet()));
Übrigens
Stream collect
garantieren Methoden nicht, dass die von ihnen generierten Sammlungen vor Änderungen geschützt sind. In Java 8 sind die von ihnen zurückgegebenen Sammlungen (z. B. -
ArrayList
,
HashSet
und
HashMap
) recht häufig (wir können sie ändern), aber dieser Umstand wird möglicherweise in zukünftigen JDK-Versionen korrigiert. Das ist fürs Erste alles über
Double brace
die Initialisierung in Java. Diese Vorlage ist für Tests und Demos geeignet, aber nicht gut genug für den Produktionseinsatz. Aufgrund seiner inhärenten Nachteile ist die Double-Brace-Initialisierung heutzutage zu einem Anti-Pattern geworden, insbesondere angesichts der verfügbaren Alternativen. Ich selbst verwende diese Konstruktion immer noch, um statische Karten zu initialisieren, und das war’s. Denn
List
ich bevorzuge das Erstellen
Collections
durch Kombinieren mit dem Erstellen
Array.asList
in seinem Konstruktor. Und wenn ich Java 8 verwende – ein Design mit der Stream-API und
collect()
.
Verwandte Artikel: Wenn Ihnen dieses Tutorial gefallen hat und Sie mehr über Java-Programmiermuster, -Prinzipien und Best Practices erfahren möchten, können Sie sich auch die anderen Artikel auf unserer Website ansehen .
Empfohlene Lektüre: Wenn Sie mehr über Muster und Best Practices erfahren möchten, sollten Sie „
Effective Programming“ von Joshua Bloch lesen . Kein Buch kann es ersetzen. Und wenn Sie bereits Java-Kenntnisse haben und ein Buch über Designmuster suchen, dessen humorvoller Präsentationsstil interessant und leicht zu lesen ist, achten Sie auf
„Head First“. Designmuster" .
Vom Übersetzer: Ich habe bewusst einen Link zu Blochs Originalbuch bereitgestellt, da dessen Übersetzung ins Russische fehlgeschlagen ist (z. B. Builder = Konstrukteur). |
Übersetzung des Artikels Was ist Double Brace Initialization in Java? Anti-Pattern-Beispiel (veröffentlicht im Oktober 2015).
GO TO FULL VERSION