Erstellen eines unveränderlichen Objekts ohne letzte Felder?

8

Können wir ein unveränderliches Objekt erstellen, ohne dass alle Felder final sind?

Wenn möglich, wären ein paar Beispiele hilfreich.

    
Vinoth Kumar C M 21.09.2011, 13:52
quelle

7 Antworten

6

Deklarieren Sie alle Felder als privat und definieren Sie nur getters:

%Vor%

unter Berufung auf @ Jon Skeet Kommentar, letzte Klasse Modifikator ist nützlich für:

  

Während eine Instanz von Nur privat unveränderlich ist, wird eine Instanz von a   Unterklasse kann durchaus veränderbar sein. Also Code, der eine Referenz vom Typ erhält   Private kann sich nicht darauf verlassen, dass es unveränderlich ist, ohne zu überprüfen, dass es ein ist   Instanz von nur privat.

Wenn Sie also sicher sein wollen, dass die Instanz, auf die Sie sich beziehen, unveränderlich ist, sollten Sie auch den letzten Klassenmodifikator verwenden.

    
Heisenbug 21.09.2011, 13:54
quelle
6

Ja, es ist - stellen Sie nur sicher, dass Ihr Staat privat ist und nichts in Ihrer Klasse mutiert es:

%Vor%

Es gibt keine Möglichkeit, den Status innerhalb dieser Klasse zu ändern, und da es endgültig ist, wissen Sie, dass keine Unterklassen einen änderbaren Status hinzufügen.

Allerdings:

  • Die Zuweisung nicht endgültiger Felder hat nicht dieselben Speichersichtbarkeitsregeln wie die letzten Felder, sodass möglicherweise das Objekt "ändern" von einem anderen Thread beobachten kann. In Abschnitt 17.5 des JLS finden Sie weitere Einzelheiten zu den Garantien für das Finale Felder.
  • Wenn Sie nicht beabsichtigen, den Feldwert zu ändern, würde ich es persönlich für unanfechtbar halten, diese Entscheidung zu dokumentieren und zu vermeiden, dass Sie später versehentlich eine Mutationsmethode hinzufügen
  • Ich kann mich nicht daran erinnern, ob die JVM verhindert, dass die letzten Felder durch Reflexion mutiert werden; offensichtlich kann jeder Aufrufer mit ausreichenden Privilegien das Feld x im obigen Code zugänglich machen und mit Reflektion mutieren. (Laut Kommentaren kann mit endgültigen Feldern gemacht werden, aber die Ergebnisse können unvorhersehbar sein.)
Jon Skeet 21.09.2011 13:54
quelle
3

Der Begriff "unveränderbar" sollte, wenn er zur Beschreibung von Java-Objekten verwendet wird, threadsichere Unveränderlichkeit bedeuten. Wenn ein Objekt unveränderlich ist, ist es im Allgemeinen selbstverständlich, dass jeder Thread denselben Zustand beobachten muss.

Single-Thread-Unveränderlichkeit ist nicht wirklich interessant. Wenn das wirklich gemeint ist, sollte es vollständig mit "single thread" qualifiziert sein; ein besserer Begriff wäre "nicht veränderbar".

Das Problem besteht darin, diese strikte Verwendung des Begriffs "unveränderlich" offiziell zu erwähnen. Ich kann nicht; Es basiert darauf, wie Java Bigshots den Begriff verwenden. Wann immer sie "unveränderliches Objekt" sagen, sprechen sie immer über Thread-sichere unveränderliche Objekte.

Die idiomatische Methode zur Implementierung unveränderlicher Objekte besteht in der Verwendung von final fields; final semantics wurde speziell aktualisiert, um unveränderliche Objekte zu unterstützen. Es ist eine sehr starke Garantie; Tatsächlich ist final fields der einzige Weg; volatile fields oder sogar synchronized block kann nicht verhindern, dass eine Objektreferenz veröffentlicht wird, bevor der Konstruktor fertig ist.

    
irreputable 21.09.2011 21:00
quelle
1

Ja, wenn Sie ein Objekt erstellen, das nur private Mitglieder enthält und keine Setter zur Verfügung stellt, wäre es unveränderlich.

    
Rig 21.09.2011 13:54
quelle
1

Eine Klasse ist unveränderlich, wenn sie keine von außen zugänglichen Methoden bereitstellt, die den Status des Objekts ändern. Also ja, Sie können eine Klasse erstellen, die unveränderlich ist, ohne die Felder endgültig zu machen. Beispiel:

%Vor%

Es ist jedoch nicht notwendig, dies in realen Programmen zu tun, und es wird empfohlen, Felder immer dann endgültig zu machen, wenn Ihre Klasse unveränderlich sein sollte.

    
Jesper 21.09.2011 13:57
quelle
1

Ich glaube, die Antwort ist ja.

beachte das folgende Objekt:

%Vor%

Dieses Objekt ist unveränderlich.

    
Karthik Ramachandran 21.09.2011 13:56
quelle
0

Ja. Machen Sie die Felder privat. Ändern Sie sie nicht in anderen Methoden als dem Konstruktor. Natürlich, warum würdest du sie nicht als endgültig bezeichnen ???

    
John B 21.09.2011 13:54
quelle

Tags und Links