Suche…


Einführung

Unveränderliche Objekte sind Instanzen, deren Zustand sich nach der Initialisierung nicht ändert. Beispielsweise ist String eine unveränderliche Klasse, und sobald sie instanziiert wird, ändert sich der Wert nie.

Bemerkungen

Einige unveränderliche Klassen in Java:

  1. java.lang.String
  2. Die Wrapper-Klassen für die primitiven Typen: java.lang.Integer, java.lang.Byte, java.lang.Character, java.lang.Short, java.lang.Boolean, java.lang.Long, java.lang.Double, java.lang.Float
  3. Die meisten Aufzählungsklassen sind unveränderlich, dies hängt jedoch vom konkreten Fall ab.
  4. java.math.BigInteger und java.math.BigDecimal (zumindest Objekte dieser Klassen selbst)
  5. java.io.File. Beachten Sie, dass dies ein Objekt außerhalb der VM (eine Datei auf dem lokalen System) darstellt, das möglicherweise existiert oder nicht vorhanden ist und über einige Methoden verfügt, die den Status dieses externen Objekts ändern und abfragen. Das File-Objekt selbst bleibt jedoch unveränderlich.

Regeln zum Definieren unveränderlicher Klassen

Die folgenden Regeln definieren eine einfache Strategie zum Erstellen unveränderlicher Objekte.

  1. Stellen Sie keine "Setter" -Methoden bereit - Methoden, die Felder oder Objekte ändern, auf die Felder verweisen.
  2. Machen Sie alle Felder endgültig und privat.
  3. Lassen Sie nicht zu, dass Unterklassen Methoden überschreiben. Am einfachsten ist es, die Klasse als final zu deklarieren. Ein komplexerer Ansatz besteht darin, den Konstruktor privat zu machen und Instanzen in Factory-Methoden zu erstellen.
  4. Wenn die Instanzfelder Verweise auf veränderliche Objekte enthalten, dürfen diese Objekte nicht geändert werden:
  5. Stellen Sie keine Methoden bereit, die die veränderbaren Objekte ändern.
  6. Verweise auf die veränderlichen Objekte nicht freigeben. Speichern Sie niemals Verweise auf externe, veränderliche Objekte, die an den Konstruktor übergeben werden. Erstellen Sie ggf. Kopien und speichern Sie Verweise auf die Kopien. Erstellen Sie auf ähnliche Weise Kopien Ihrer internen veränderbaren Objekte, wenn dies erforderlich ist, um zu vermeiden, dass die Originale in Ihren Methoden zurückgegeben werden.

Beispiel ohne mutable refs

public final class Color {
    final private int red;
    final private int green;
    final private int blue;

    private void check(int red, int green, int blue) {
        if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) {
            throw new IllegalArgumentException();
        }
    }

    public Color(int red, int green, int blue) {
        check(red, green, blue);
        this.red = red;
        this.green = green;
        this.blue = blue;
    }

    public Color invert() {
        return new Color(255 - red, 255 - green, 255 - blue);
    }
}

Beispiel mit veränderlichen Refs

In diesem Fall ist die Klasse Point veränderbar und einige Benutzer können den Objektstatus dieser Klasse ändern.

class Point {
    private int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }
    
    public void setX(int x) {
        this.x = x;
    }
    
    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

//...

public final class ImmutableCircle {
    private final Point center;
    private final double radius;

    public ImmutableCircle(Point center, double radius) {
        // we create new object here because it shouldn't be changed
        this.center = new Point(center.getX(), center.getY());
        this.radius = radius;
    }

Was ist der Vorteil der Unveränderlichkeit?

Der Vorteil der Unveränderlichkeit liegt in der Parallelität. Es ist schwierig, die Korrektheit in veränderlichen Objekten aufrechtzuerhalten, da mehrere Threads versuchen könnten, den Zustand des gleichen Objekts zu ändern, was dazu führt, dass einige Threads einen unterschiedlichen Zustand des gleichen Objekts sehen, abhängig vom Zeitpunkt der Lese- und Schreibvorgänge Objekt.

Mit einem unveränderlichen Objekt kann sichergestellt werden, dass alle Threads, die das Objekt betrachten, denselben Status sehen, da sich der Status eines unveränderlichen Objekts nicht ändert.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow