Wie erstellt man eine Unveränderliche Klasse in Java
Einführung
Dieser Artikel gibt einen Überblick darüber, wie man eine unveränderliche Klasse in Java erstellt.
Ein Objekt ist unveränderlich, wenn sich sein Zustand nach der Initialisierung nicht mehr ändert. Zum Beispiel ist die Klasse String eine unveränderliche Klasse, und sobald ein String-Objekt erstellt ist, ändert sich dessen Wert nicht mehr.
Da ein unveränderliches Objekt nicht aktualisiert werden kann, muss für jede Zustandsänderung ein neues Objekt erstellt werden. Unveränderliche Objekte haben jedoch die folgenden Vorteile:
- Gut für Caching, da man sich keine Gedanken über Wertänderungen machen muss.
- Von Natur aus thread-sicher, wodurch Thread-Sicherheitsprobleme in Multi-Threading-Umgebungen entfallen.
Unveränderliche Klassen in Java erstellen
Um eine unveränderliche Klasse zu erstellen, befolgen Sie diese Prinzipien:
- Deklarieren Sie die Klasse als
final
, damit sie nicht erweitert werden kann. - Machen Sie alle Felder
private
, um direkten Zugriff zu verhindern. - Bieten Sie keine Setter-Methoden für Variablen an.
- Machen Sie veränderliche Felder
final
, sodass sie nur einmal zugewiesen werden können. - Initialisieren Sie Felder mithilfe eines Konstruktors, der eine Deep Copy durchführt.
- Klonen Sie Objekte in Getter-Methoden, um Kopien zurückzugeben, nicht die ursprüngliche Objektreferenz.
Beispielcode
import java.util.HashMap;
import java.util.Iterator;
public final class FinalClassExample {
private final int id;
private final String name;
private final HashMap<String, String> testMap;
public int getId() {
return id;
}
public String getName() {
return name;
}
public HashMap<String, String> getTestMap() {
return (HashMap<String, String>) testMap.clone();
}
public FinalClassExample(int i, String n, HashMap<String, String> hm) {
System.out.println("Performing Deep Copy for Object initialization");
this.id = i;
this.name = n;
HashMap<String, String> tempMap = new HashMap<>();
Iterator<String> it = hm.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
tempMap.put(key, hm.get(key));
}
this.testMap = tempMap;
}
public static void main(String[] args) {
HashMap<String, String> h1 = new HashMap<>();
h1.put("1", "first");
h1.put("2", "second");
String s = "original";
int i = 10;
FinalClassExample ce = new FinalClassExample(i, s, h1);
System.out.println("ce id: " + ce.getId());
System.out.println("ce name: " + ce.getName());
System.out.println("ce testMap: " + ce.getTestMap());
i = 20;
s = "modified";
h1.put("3", "third");
System.out.println("ce id after local variable change: " + ce.getId());
System.out.println("ce name after local variable change: " + ce.getName());
System.out.println("ce testMap after local variable change: " + ce.getTestMap());
HashMap<String, String> hmTest = ce.getTestMap();
hmTest.put("4", "new");
System.out.println("ce testMap after changing variable from getter methods: " + ce.getTestMap());
}
}
Ausgabe
Performing Deep Copy for Object initialization
ce id: 10
ce name: original
ce testMap: {1=first, 2=second}
ce id after local variable change: 10
ce name after local variable change: original
ce testMap after local variable change: {1=first, 2=second}
ce testMap after changing variable from getter methods: {1=first, 2=second}
Was passiert ohne Deep Copy
public HashMap<String, String> getTestMap() {
return testMap;
}
Das Objekt ist nicht mehr unveränderlich. Änderungen an der HashMap beeinflussen direkt das Objekt.
Beispielausgabe der Unveränderliche Klassen in Java
Performing Shallow Copy for Object initialization
ce id: 10
ce name: original
ce testMap: {1=first, 2=second}
ce id after local variable change: 10
ce name after local variable change: original
ce testMap after local variable change: {1=first, 2=second, 3=third}
ce testMap after changing variable from getter methods: {1=first, 2=second, 3=third, 4=new}
Fazit über Unveränderliche Klassen in Java
Das Erstellen unveränderlicher Klassen erfordert ein durchdachtes Design, insbesondere die Implementierung von Deep Copy. Dieser Ansatz sorgt dafür, dass der Zustand eines Objekts unverändert bleibt, selbst in komplexen Szenarien. Unveränderliche Klassen sind zudem von Natur aus thread-sicher, da keine unvorhergesehenen Änderungen auftreten können. Dies macht sie besonders wertvoll in Multi-Threading-Umgebungen, in denen Konsistenz entscheidend ist. Darüber hinaus tragen sie zur verbesserten Wartbarkeit und Lesbarkeit von Code bei. Die Objektintegrität bleibt geschützt, da keine direkten Änderungen an Feldern möglich sind. Erkunden Sie weiterführende Java-Tutorials, um Ihre Programmierfähigkeiten auszubauen und tiefere Einblicke in die Welt der Softwareentwicklung zu gewinnen.