サーチ…


前書き

不変オブジェクトは、インスタンスが初期化された後に状態が変化しないインスタンスです。たとえば、Stringは不変クラスであり、インスタンス化されるとその値は決して変更されません。

備考

Javaのいくつかの不変クラス:

  1. java.lang.String
  2. プリミティブ型のラッパークラス: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. ほとんどのenumクラスは不変ですが、実際これは具体的な場合に依存します。
  4. java.math.BigIntegerとjava.math.BigDecimal(少なくともクラス自体のオブジェクト)
  5. java.io.File。これは、VM外部のオブジェクト(ローカルシステム上のファイル)を表し、存在する場合と存在しない場合があり、この外部オブジェクトの状態を変更および照会するいくつかのメソッドがあります。しかし、Fileオブジェクト自体は不変のままです。

不変クラスを定義するための規則

次の規則は、不変オブジェクトを作成するための簡単な戦略を定義しています。

  1. フィールドで参照されるフィールドやオブジェクトを変更するメソッドである "setter"メソッドを提供しないでください。
  2. すべてのフィールドを最終的かつプライベートにする。
  3. サブクラスによるメソッドのオーバーライドを許可しないでください。これを行う最も簡単な方法は、クラスをfinalとして宣言することです。より洗練されたアプローチは、コンストラクタをプライベートにして、ファクトリメソッドでインスタンスを構築することです。
  4. インスタンスフィールドに変更可能なオブジェクトへの参照が含まれている場合は、それらのオブジェクトの変更を許可しないでください。
  5. 変更可能なオブジェクトを変更するメソッドを提供しないでください。
  6. 変更可能なオブジェクトへの参照を共有しないでください。コンストラクタに渡された外部の変更可能なオブジェクトへの参照を保存しないでください。必要に応じてコピーを作成し、コピーへの参照を保存します。同様に、メソッド内でオリジナルを返さないように、必要に応じて内部可変オブジェクトのコピーを作成します。

可変参照がない例

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

可変参照型の例

この場合、クラスPointは変更可能であり、このクラスのオブジェクトの状態を変更できるユーザもいます。

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

不変性の利点は何ですか?

不変性の利点は並行性にあります。複数のスレッドが同じオブジェクトの状態を変更しようとしている可能性があり、同じオブジェクトの異なる状態を見ているスレッドにつながる可能性があるため、変更可能なオブジェクトの正確性を維持することは難しいオブジェクト。

不変オブジェクトを持つことによって、不変オブジェクトの状態が変わらないので、オブジェクトを見ているすべてのスレッドが同じ状態を見ることを保証することができます。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow