Wie erstelle ich unveränderliche Objekte in Java?
Welche Objekte sollten als unveränderlich bezeichnet werden?
Wenn ich eine Klasse mit allen statischen Mitgliedern habe, ist sie unveränderlich?
java
immutability
Neel Salpe
quelle
quelle
Antworten:
Nachfolgend sind die harten Anforderungen an ein unveränderliches Objekt aufgeführt.
final
, das Objekt jedoch weiterhin veränderbar sein kannprivate final Date imStillMutable
). Sie solltendefensive copies
in diesen Fällen machen.Die Gründe für die Erstellung der Klasse
final
sind sehr subtil und werden oft übersehen. Wenn es nicht endgültig ist, können Personen Ihre Klasse frei erweitern, überschreibenpublic
oderprotected
verhalten, veränderbare Eigenschaften hinzufügen und dann ihre Unterklasse als Ersatz angeben. Indem Sie die Klasse deklarierenfinal
, können Sie sicherstellen, dass dies nicht geschieht.Um das Problem in Aktion zu sehen, betrachten Sie das folgende Beispiel:
In der Praxis tritt das obige Problem häufig in Umgebungen mit Abhängigkeitsinjektion auf. Sie instanziieren Dinge nicht explizit und die Superklassenreferenz, die Sie erhalten, kann tatsächlich eine Unterklasse sein.
Um harte Garantien für die Unveränderlichkeit zu geben, muss die Klasse als markiert werden
final
. Dies wird in Joshua Blochs Effective Java ausführlich behandelt und in der Spezifikation für das Java-Speichermodell explizit erwähnt .quelle
Fügen Sie der Klasse nur keine öffentlichen Mutator-Methoden (Setter-Methoden) hinzu.
quelle
private
oder die Klasse sollte seinfinal
. Nur um Vererbung zu vermeiden. Weil die Vererbung die Kapselung verletzt.Klassen sind nicht unveränderlich, Objekte sind.
Unveränderlich bedeutet: Mein öffentlich sichtbarer Zustand kann sich nach der Initialisierung nicht ändern.
Felder müssen nicht als endgültig deklariert werden, obwohl dies enorm zur Gewährleistung der Gewindesicherheit beitragen kann
Wenn Ihre Klasse nur statische Elemente hat, sind Objekte dieser Klasse unveränderlich, da Sie den Status dieses Objekts nicht ändern können (wahrscheinlich können Sie es auch nicht erstellen :))
quelle
Um eine Klasse in Java unveränderlich zu machen, können Sie die folgenden Punkte beachten:
1. Stellen Sie keine Setter-Methoden bereit, um die Werte einer der Instanzvariablen der Klasse zu ändern.
2. Deklarieren Sie die Klasse als 'final' . Dies würde verhindern, dass eine andere Klasse sie erweitert und somit eine Methode überschreibt, die Instanzvariablenwerte ändern könnte.
3. Deklarieren Sie die Instanzvariablen als privat und endgültig .
4. Sie können den Konstruktor der Klasse auch als privat deklarieren und bei Bedarf eine Factory-Methode hinzufügen, um eine Instanz der Klasse zu erstellen.
Diese Punkte sollten helfen !!
quelle
private
?Von Oracle - Website, wie unveränderliche Objekte in Java erstellen.
quelle
Ein unveränderliches Objekt ist ein Objekt, das seinen internen Status nach der Erstellung nicht ändert. Sie sind in Multithread-Anwendungen sehr nützlich, da sie ohne Synchronisierung von Threads gemeinsam genutzt werden können.
Um ein unveränderliches Objekt zu erstellen, müssen Sie einige einfache Regeln befolgen:
1. Fügen Sie keine Setter-Methode hinzu
Wenn Sie ein unveränderliches Objekt erstellen, ändert sich sein interner Status niemals. Die Aufgabe einer Setter-Methode besteht darin, den internen Wert eines Felds so zu ändern, dass Sie ihn nicht hinzufügen können.
2. Deklarieren Sie alle Felder als endgültig und privat
Ein privates Feld ist von außerhalb der Klasse nicht sichtbar, sodass keine manuellen Änderungen darauf angewendet werden können.
Wenn Sie ein Feld final deklarieren, wird garantiert, dass sich der Wert niemals ändert, wenn er auf einen primitiven Wert verweist, wenn er auf ein Objekt verweist. Die Referenz kann nicht geändert werden. Dies reicht nicht aus, um sicherzustellen, dass ein Objekt mit nur privaten Endfeldern nicht veränderbar ist.
3. Wenn ein Feld ein veränderbares Objekt ist, erstellen Sie defensive Kopien davon für Getter-Methoden
Wir haben zuvor gesehen, dass die Definition eines Feldes final und private nicht ausreicht, da es möglich ist, seinen internen Status zu ändern. Um dieses Problem zu lösen, müssen wir eine defensive Kopie dieses Feldes erstellen und dieses Feld jedes Mal zurückgeben, wenn es angefordert wird.
4. Wenn ein an den Konstruktor übergebenes veränderbares Objekt einem Feld zugewiesen werden muss, erstellen Sie eine defensive Kopie davon
Das gleiche Problem tritt auf, wenn Sie eine an den Konstruktor übergebene Referenz enthalten, da diese geändert werden kann. Wenn Sie also einen Verweis auf ein an den Konstruktor übergebenes Objekt halten, können veränderbare Objekte erstellt werden. Um dieses Problem zu lösen, muss eine defensive Kopie des Parameters erstellt werden, wenn es sich um veränderbare Objekte handelt.
Beachten Sie, dass es nicht ausreicht, das Feld als endgültig und privat zu definieren , wenn ein Feld eine Referenz auf ein unveränderliches Objekt ist, um defensive Konstruktionen davon im Konstruktor und in den Getter-Methoden zu erstellen.
5. Unterklassen dürfen Methoden nicht überschreiben
Wenn eine Unterklasse eine Methode überschreibt, kann sie den ursprünglichen Wert eines veränderlichen Feldes anstelle einer defensiven Kopie davon zurückgeben.
Um dieses Problem zu lösen, können Sie einen der folgenden Schritte ausführen:
Wenn Sie diese einfachen Regeln befolgen, können Sie Ihre unveränderlichen Objekte frei zwischen Threads teilen, da diese threadsicher sind!
Im Folgenden sind einige bemerkenswerte Punkte aufgeführt:
Es gibt kein Richtig oder Falsch, es kommt nur darauf an, was Sie bevorzugen. Es hängt nur von Ihren Vorlieben ab und davon, was Sie erreichen möchten (und beide Ansätze problemlos anwenden zu können, ohne eingefleischte Fans der einen oder anderen Seite zu entfremden, ist ein heiliger Gral, nach dem einige Sprachen suchen).
quelle
quelle
Zunächst wissen Sie, warum Sie ein unveränderliches Objekt erstellen müssen und welche Vorteile ein unveränderliches Objekt bietet.
Vorteile eines unveränderlichen Objekts
Parallelität und Multithreading Es ist automatisch threadsicher, so dass Synchronisationsprobleme auftreten ... usw.
Sie brauchen nicht zu Konstruktor kopieren nicht brauchen , um die Umsetzung von Klon. Klasse kann nicht überschrieben werden Machen Sie das Feld als privaten und endgültigen Aufrufer, ein Objekt vollständig in einem einzigen Schritt zu erstellen , anstatt einen Konstruktor ohne Argumente zu verwenden
Unveränderliche Objekte sind einfach Objekte, deren Status bedeutet, dass sich die Daten des Objekts nicht ändern können, nachdem das unveränderliche Objekt erstellt wurde.
Bitte beachten Sie den folgenden Code.
quelle
Mutabilität minimieren
Eine unveränderliche Klasse ist einfach eine Klasse, deren Instanzen nicht geändert werden können. Alle in jeder Instanz enthaltenen Informationen werden beim Erstellen bereitgestellt und sind für die Lebensdauer des Objekts festgelegt.
Unveränderliche JDK-Klassen: String, die Boxed-Primitive-Klassen (Wrapper-Klassen), BigInteger und BigDecimal usw.
Wie macht man eine Klasse unveränderlich?
Machen Sie defensive Kopien. Stellen Sie den exklusiven Zugriff auf veränderbare Komponenten sicher.
öffentliche Liste getList () {return Collections.unmodizableList (Liste); <=== defensive Kopie des veränderlichen Feldes, bevor es an den Aufrufer zurückgegeben wird}
Wenn Ihre Klasse Felder enthält, die auf veränderbare Objekte verweisen, stellen Sie sicher, dass Clients der Klasse keine Verweise auf diese Objekte erhalten können. Initialisieren Sie ein solches Feld niemals mit einer vom Client bereitgestellten Objektreferenz oder geben Sie die Objektreferenz von einem Accessor zurück.
Weitere Informationen finden Sie in meinem Blog:
http://javaexplorer03.blogspot.in/2015/07/minimize-mutability.html
quelle
Ein Objekt wird als unveränderlich bezeichnet, wenn sein Status nach dem Erstellen nicht mehr geändert werden kann. Eine der einfachsten Möglichkeiten, unveränderliche Klassen in Java zu erstellen, besteht darin, alle Felder als endgültig festzulegen. Wenn Sie unveränderliche Klassen schreiben müssen, die veränderbare Klassen wie "java.util.Date" enthalten. Um die Unveränderlichkeit in solchen Fällen zu bewahren, wird empfohlen, eine Kopie des Originalobjekts zurückzugeben.
quelle
Unveränderliche Objekte sind Objekte, deren Status nach ihrer Erstellung nicht mehr geändert werden kann. Beispielsweise ist die String-Klasse eine unveränderliche Klasse. Unveränderliche Objekte können nicht geändert werden, sodass sie bei gleichzeitiger Ausführung auch threadsicher sind.
Merkmale unveränderlicher Klassen:
Schlüssel zum Schreiben einer unveränderlichen Klasse:
quelle
Die folgenden Schritte müssen berücksichtigt werden, wenn Sie eine Klasse als unveränderliche Klasse möchten.
Werfen wir einen Blick auf das, was wir oben eingegeben haben:
quelle
Häufig ignorierte, aber wichtige Eigenschaften für unveränderliche Objekte
Hinzufügen von mehr als auf die Antwort , die von @ nsfyn55 die folgenden Aspekte müssen auch für Objekt Unveränderlichkeit in Betracht gezogen werden, die von sind prime Bedeutung
Betrachten Sie die folgenden Klassen:
Es folgt die Ausgabe von MutabilityCheck:
Es ist wichtig sich das zu merken,
Konstruieren veränderlicher Objekte auf einem unveränderlichen Objekt (über den Konstruktor), entweder durch 'Kopieren' oder 'Cloing' in Instanzvariablen der unveränderlichen Objekte, die durch die folgenden Änderungen beschrieben werden:
gewährleistet immer noch keine vollständige Unveränderlichkeit, da Folgendes aus der Klasse MutabilityCheck weiterhin gültig ist:
Das Ausführen von MutabilityCheck mit den in 1. vorgenommenen Änderungen führt jedoch zu folgender Ausgabe:
Um eine vollständige Unveränderlichkeit für ein Objekt zu erreichen, müssen auch alle seine abhängigen Objekte unveränderlich sein
quelle
Ab JDK 14+ mit JEP 359 können wir "
records
" verwenden. Es ist die einfachste und stressfreieste Art, unveränderliche Klassen zu erstellen.Eine Datensatzklasse ist ein flach unveränderlicher , transparenter Träger für einen festen Satz von Feldern, der als Datensatz bezeichnet
components
wird und einestate
Beschreibung für den Datensatz enthält. Jedescomponent
führt zu einemfinal
Feld, das den angegebenen Wert enthält, und eineraccessor
Methode zum Abrufen des Werts. Der Feldname und der Zugriffsname stimmen mit dem Namen der Komponente überein.Betrachten wir das Beispiel zum Erstellen eines unveränderlichen Rechtecks
Keine Notwendigkeit, einen Konstruktor zu deklarieren, keine Notwendigkeit,
equals
&hashCode
Methoden zu implementieren . Nur alle Datensätze benötigen einen Namen und eine Statusbeschreibung.Wenn Sie den Wert während der Objekterstellung überprüfen möchten, müssen wir den Konstruktor explizit deklarieren.
Der Datensatzkörper kann statische Methoden, statische Felder, statische Initialisierer, Konstruktoren, Instanzmethoden und verschachtelte Typen deklarieren.
Instanzmethoden
statische Felder, Methoden
Da state Teil der Komponenten sein sollte, können wir Datensätzen keine Instanzfelder hinzufügen. Wir können jedoch statische Felder und Methoden hinzufügen:
quelle