2

不変オブジェクトの場合、含まれているコレクションを変更不可能としてラップするのはどこが適切ですか?3つのオプションがあります。

  1. 不変オブジェクトのファクトリでは:

    public class ImmutableFactory {
    
        public Immutable build(){
           List<Integer> values = new ArrayList<Integer>();
    
            values.add(1);
            values.add(2);
            values.add(3);
    
            return new Immutable(Collections.unmodifiableList(values), "hello");
        }
    }
    
  2. 不変のコンストラクターで

    public class Immutable {
    
        private final List<Integer> values;
        private final String hello;
    
        public Immutable(List<Integer> values, String hello) {
            this.values = Collections.unmodifiableList(values);
           this.hello = hello;
        }
    
        public List<Integer> getValues() {
            return values;
        }
    
        public String getHello() {
            return hello;
        }
    }
    
  3. 不変のアクセサー(該当する場合)。

    public class Immutable {
    
        private final List<Integer> values;
        private final String hello;
    
        public Immutable(List<Integer> values, String hello) {
            this.values = values;
            this.hello = hello;
        }
    
        public List<Integer> getValues() {
            return Collections.unmodifiableList(values);
        }
    
        public String getHello() {
            return hello;
        }
    }
    

他にオプションはありますか?どれが適切ですか?

4

2 に答える 2

4

Immutableコレクションを作成する場合は、コンストラクターへの引数として指定されたリストを変更する誰かから身を守る必要があります。保護的にコピーする必要があります。

public Immutable(List<Integer> values, String hello) {
    this.values = Collections.unmodifiableList(new ArrayList<Integer>(values));
    this.hello = hello;
}

不変のコレクションのインターフェースを見つけることができるので、私はずっと前にGuavaコレクションに切り替えました。コンストラクターは次のようになります。

public Immutable(ImmutableList<Integer> values, String hello) {
    this.values = values;
    this.hello = hello;
}

あなたが受け取る議論は誰によっても変更されないことを確信しているでしょう。

通常、不変のクラス内で不変のリストへの参照を保持することをお勧めします。これにより、誤って変更しないことが保証されます。

私の意見では、ケース(1)は、ファクトリメソッドが不変のコレクションを作成する唯一の方法である場合にのみ意味があり、それでも誰かがこれらのクラスをリファクタリングすると壊れることがあります。他の制限がない限り、自給自足のクラスを作成することが常に最善です。

于 2012-09-16T21:53:40.067 に答える
1

まず第一に、すべての場所のコードは確かに不変ですが、それはanIntegerが不変だからです。代わりに
持っていた場合、リストの個々が不変であることは保証されません。そのためにはコーディングする必要があります そうは言っても、別のオプションは、リストの防御的なディープコピーを行うことです。このアプローチは、不変性も提供します。private final List<SomeCustomClass> values;Collections.unmodifiableList(values);SomeCustomClass

于 2012-09-16T22:05:48.727 に答える