2

セッターが呼び出された後、オブジェクトを外部から変更できないようにしたい場合、ベストで一般的な方法と考えられるものは何ですか? コードには、2 つのオプションのジレンマを使用した、簡単で自己説明的な詳細な例があります。

//caller scope
CustomObject original = new CustomObject(params...);  //original state 1
MyClass mMyClass = new MyClass(original);
original.modifyMe(params...);  //original state 2
mMyClass.setCustomObject(original);
original.modifyMe(params...); //original state 3


/*!!!REQUIREMENT: mMyClass.CustomObject should be in state 2!!!*/


class MyClass {

    private CustomObject mObject;

    public MyClass() {
        this.mObject = new CustomObject();
    }

    public MyClass(CustomObject obj) {
        this.mObject = obj.Clone();
    }

    //mObject is private, modified only through setter
    public getCustomObject() {
        return this.mObject;
    }

    public setCustomObject(CustomObject obj) {
        //Option 1 in the caller  
        //mMyClass.setCustomObject(new CustomObject(params...));
        this.mObject = obj;

        //Option 2 in the caller
        //mMyClass.setCustomObject(callerCustomObject);
        this.mObject = obj.Clone();
    }

}
4

1 に答える 1

1

ここではクローンを使用しません。非効率的な防御コピーを作成するのではなく、CustomObject を不変にしてみてください。withXXX メソッド (setXXXX とほぼ同等) を追加することで状態を変更できますが、(渡されるオブジェクトではなく) ホスト オブジェクトの新しいインスタンスを作成します。プロジェクト lombokには、Withers を使用して不変オブジェクトを作成するための便利なプリプロセッサ アノテーションが付属しています。Immutables 2.0 プロジェクトも参照してください。

@AllArgsConstructor
class CustomObject {

   @Wither @Getter
   private final int state;

}

CustomObject one = new CustomObject(1);
CustomObject two = one.withState(2);

assertThat(one.getState(),equalTo(1));
assertThat(two.getState(),equalTo(2));

本物の不変オブジェクトを使用することで、メモリ (および GC) と CPU のオーバーヘッドが防御的コピーよりもはるかに少なくなり、コードがはるかに単純になります。

于 2015-09-19T10:37:42.330 に答える