Unveränderliche Objekte in Java

Unveränderliche Objekte in Java

1. Überblick

In diesem Tutorial erfahren Sie, was ein Objekt unveränderlich macht, wie Unveränderlichkeit in Java erreicht wird und welche Vorteile dies mit sich bringt.

2. Was ist ein unveränderliches Objekt?

Ein unveränderliches Objekt ist einobject whose internal state remains constant after it has been entirely created.

Dies bedeutet, dass die öffentliche API eines unveränderlichen Objekts uns garantiert, dass es sich während seiner gesamten Lebensdauer auf die gleiche Weise verhält.

Wenn wir uns die KlasseString ansehen, können wir sehen, dass sich die ursprünglichenString nicht ändern, selbst wenn ihre API uns mit ihrerreplace-Methode ein veränderliches Verhalten zu bieten scheint:

String name = "example";
String newName = name.replace("dung", "----");

assertEquals("example", name);
assertEquals("bael----", newName);

Die API bietet schreibgeschützte Methoden. Sie sollte niemals Methoden enthalten, die den internen Status des Objekts ändern.

3. Das Schlüsselwortfinal in Java

Bevor wir versuchen, Unveränderlichkeit in Java zu erreichen, sollten wir über das Schlüsselwortfinalprechen.

In Javavariables are mutable by default, meaning we can change the value they hold.

Durch die Verwendung des Schlüsselwortsfinal beim Deklarieren einer Variablen lässt der Java-Compiler den Wert dieser Variablen nicht ändern. Stattdessen wird ein Fehler beim Kompilieren gemeldet:

final String name = "example";
name = "bael...";

Beachten Sie, dassfinal uns nur verbietet, die Referenz zu ändern, die die Variable enthält. Es schützt uns nicht davor, den internen Status des Objekts, auf das es verweist, mithilfe seiner öffentlichen API zu ändern:

final List strings = new ArrayList<>();
assertEquals(0, strings.size());
strings.add("example");
assertEquals(0, strings.size());

Das zweiteassertEquals schlägt fehl, da das Hinzufügen eines Elements zur Liste seine Größe ändert. Daher ist es kein unveränderliches Objekt.

4. Unveränderlichkeit in Java

Nachdem wir nun wissen, wie Änderungen am Inhalt einer Variablen vermieden werden, können wir damit die API unveränderlicher Objekte erstellen.

Um die API eines unveränderlichen Objekts zu erstellen, müssen wir sicherstellen, dass sich sein interner Status nicht ändert, unabhängig davon, wie wir seine API verwenden.

Ein Schritt vorwärts in die richtige Richtung ist die Verwendung vonfinal bei der Deklaration seiner Attribute:

class Money {
    private final double amount;
    private final Currency currency;

    // ...
}

Beachten Sie, dass Java uns garantiert, dass sich der Wert vonamountnicht ändert. Dies ist bei allen primitiven Typvariablen der Fall.

In unserem Beispiel wird jedoch nur garantiert, dass sich diecurrency nicht ändern, alsowe must rely on the CurrencyAPI to protect itself from changes.

In den meisten Fällen benötigen wir die Attribute eines Objekts, um benutzerdefinierte Werte zu speichern, und der Ort, an dem der interne Zustand eines unveränderlichen Objekts initialisiert wird, ist sein Konstruktor:

class Money {
    // ...
    public Money(double amount, Currency currency) {
        this.amount = amount;
        this.currency = currency;
    }

    public Currency getCurrency() {
        return currency;
    }

    public double getAmount() {
        return amount;
    }
}

Wie bereits erwähnt, verfügt unsereMoney-Klasse nur über schreibgeschützte Methoden, um die Anforderungen einer unveränderlichen API zu erfüllen.

Mit der Reflection-API können wir Unveränderlichkeit undchange immutable objects aufheben. Die Reflexion verstößt jedoch gegen die öffentliche API des unveränderlichen Objekts. In der Regel sollten wir dies vermeiden.

5. Leistungen

Da der interne Zustand eines unveränderlichen Objekts zeitlich konstant bleibt, beträgtwe can share it safely among multiple threads.

Wir können es auch frei verwenden, und keines der Objekte, die darauf verweisen, wird einen Unterschied bemerken. Wir können sagen, dassimmutable objects are side-effects free.

6. Fazit

Unveränderliche Objekte ändern ihren internen Zustand nicht rechtzeitig, sie sind threadsicher und frei von Nebenwirkungen. Aufgrund dieser Eigenschaften eignen sich unveränderliche Objekte auch besonders für Umgebungen mit mehreren Threads.

Sie finden die in diesem Artikel verwendeten Beispieleover on GitHub.