Ricerca…


introduzione

Gli oggetti immutabili sono istanze il cui stato non cambia dopo che è stato inizializzato. Ad esempio, String è una classe immutabile e una volta istanziata il suo valore non cambia mai.

Osservazioni

Alcune classi immutabili in Java:

  1. java.lang.String
  2. Le classi wrapper per i tipi primitivi: 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. La maggior parte delle classi di enume è immutabile, ma in realtà dipende dal caso concreto.
  4. java.math.BigInteger e java.math.BigDecimal (almeno oggetti di quelle stesse classi)
  5. java.io.File. Si noti che questo rappresenta un oggetto esterno alla VM (un file sul sistema locale), che può o non può esistere e che ha alcuni metodi di modifica e interrogazione dello stato di questo oggetto esterno. Ma l'oggetto File stesso rimane immutabile.

Regole per definire classi immutabili

Le seguenti regole definiscono una strategia semplice per la creazione di oggetti immutabili.

  1. Non fornire metodi "setter" - metodi che modificano campi o oggetti cui fanno riferimento i campi.
  2. Rendi tutti i campi definitivi e privati.
  3. Non consentire alle sottoclassi di sovrascrivere i metodi. Il modo più semplice per farlo è dichiarare la classe come definitiva. Un approccio più sofisticato è rendere privato il costruttore e costruire istanze in metodi di fabbrica.
  4. Se i campi dell'istanza includono riferimenti a oggetti mutabili, non consentire la modifica di tali oggetti:
  5. Non fornire metodi che modificano gli oggetti mutabili.
  6. Non condividere riferimenti agli oggetti mutabili. Non memorizzare mai riferimenti a oggetti esterni mutabili trasmessi al costruttore; se necessario, creare copie e memorizzare i riferimenti alle copie. Allo stesso modo, crea copie dei tuoi oggetti interni mutabili quando necessario per evitare di restituire gli originali nei tuoi metodi.

Esempio senza riferimenti mutabili

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);
    }
}

Esempio con riferimenti mutabili

In questo caso la classe Point è mutabile e alcuni utenti possono modificare lo stato dell'oggetto di questa classe.

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;
    }

Qual è il vantaggio dell'immutabilità?

Il vantaggio dell'immutabilità viene fornito con la concorrenza. È difficile mantenere la correttezza in oggetti mutabili, poiché più thread potrebbero tentare di cambiare lo stato dello stesso oggetto, portando a qualche thread che vede uno stato diverso dello stesso oggetto, a seconda della sincronizzazione delle letture e delle scritture su detto oggetto.

Avendo un oggetto immutabile, è possibile garantire che tutti i thread che guardano l'oggetto vedranno lo stesso stato, poiché lo stato di un oggetto immutabile non cambierà.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow