Es gibt einige Fälle, in denen Sie unveränderliche Karten, Listen, Mengen oder andere Arten von Sammlungen bevorzugen.
Der erste und wohl wichtigste Anwendungsfall ist, wenn Sie ein Ergebnis einer Abfrage oder einer Berechnung zurückgeben, die eine Menge (oder Liste oder Karte) von Ergebnissen zurückgeben würde, die Verwendung unveränderlicher Datenstrukturen vorzuziehen.
In diesem Fall ziehe ich es vor, unveränderliche Versionen davon zurückzugeben, da dies die tatsächliche Unveränderlichkeit einer Ergebnismenge einer Berechnung viel deutlicher widerspiegelt - unabhängig davon, was Sie später mit den Daten tun, sollte die Menge der Ergebnisse, die Sie von Ihrer Abfrage erhalten haben, dies nicht tun Veränderung.
Der zweite häufige Anwendungsfall ist, wenn Sie ein Argument als Eingabe für eine Methode oder einen Dienst angeben müssen. Es sei denn, Sie erwarten die Eingabesammlung durch den Dienst oder die Methode geändert wird (was normalerweise eine wirklich schlechte Entwurfsidee ist), kann die Übergabe einer unveränderlichen Sammlung anstelle der veränderlichen in vielen Fällen die vernünftige und sichere Wahl sein.
Ich betrachte es als "Pass by Value" -Konvention.
Allgemeiner gesagt - es ist sinnvoll, unveränderliche Datenstrukturen zu verwenden, wenn Daten Modul- oder Dienstgrenzen überschreiten. Dies macht es viel einfacher, über Unterschiede zwischen (unveränderlichem) Input / Output und veränderlichem internen Zustand nachzudenken.
Als sehr vorteilhafter Nebeneffekt ist dies eine erhöhte Sicherheit und Thread-Sicherheit Ihrer Module / Dienste und sorgt für eine sauberere Trennung von Bedenken.
Ein weiterer guter Grund für die Anwendung von Collections.empty*()
Methoden ist der spürbare Mangel an Ausführlichkeit. In der Zeit vor Java7 mussten Sie, wenn Sie eine generische Sammlung hatten, generische Typanmerkungen überall verteilen.
Vergleichen Sie einfach diese beiden Erklärungen:
Map<Foo, Comparable<? extends Bar>> fooBarMap = new HashMap<Foo, Comparable<? extends Bar>>();
gegen:
Map<Foo, Comparable<? extends Bar>> fooBarMap = Collections.emptyMap();
Letzteres gewinnt auf zwei wichtige Arten zweifellos die Lesbarkeit:
- In der ersten Deklaration ist die gesamte Instanziierung einer leeren Karte im Rauschen generischer Typdeklarationen vergraben, wodurch eine im Wesentlichen triviale Deklaration viel kryptischer wird, als sie sein muss.
- Zusätzlich zum bemerkenswerten Fehlen einer generischen Typanmerkung auf der rechten Seite wird in der zweiten Version eindeutig angegeben, dass die Karte mit einer leeren Karte initialisiert wird. Da ich weiß, dass diese Methode eine unveränderliche Karte zurückgibt, ist es für mich jetzt einfacher zu finden, wo
fooBarMap
ein anderer nicht leerer Wert zugewiesen wird, indem ich nur nach suche /fooBarMap =/
.