3

Immutableクラスの作成に関する質問があります。私が考慮している点は次のとおりです。

  1. クラスをファイナルにする
  2. すべてのメンバーをfinalにし、明示的に、静的ブロックで、またはコンストラクターで設定します
  3. すべてのメンバーを非公開にする
  4. 状態を変更するメソッドはありません
  5. 可変メンバーコンポーネントへのアクセスを制限するように細心の注意を払ってください(フィールドはfinalである可能性がありますが、オブジェクトは依然として可変である可能性があります。つまり、private final Date imStillMutable)-詳細については、防御コピーまたはその従兄弟コピーコンストラクターを参照してください。


でも、5点が全然わからなかったので、その例で5点がはっきりしている例を教えてください。

4

2 に答える 2

5

ポイント5は、可変オブジェクトに関係する何かを返すメソッドがあるときはいつでも、プライベート状態に依存しないコピーを作成することをお勧めします。例えば:

public final class Foo
{
    private final List<String> strings;

    public Foo(List<String> strings)
    {
        // Defensive copy on construction. Protects from constructing
        // code mutating the list.
        this.strings = new ArrayList<String>(strings);
    }

    public List<String> getStrings()
    {
        // Defensive copy on read. Protects from clients mutating the list.
        return new ArrayList<String>(strings);
    }
}

防御コピーは、状態が変更可能な場合にのみ必要であることに注意してください。たとえば、上記のクラスの状態として(たとえば、Guavaからの)を使用した場合、 (入力も)ではなくImmutableList構築時に新しいリストを作成する必要があります。ImmutableListgetStrings

また、この場合Stringは不変であるため、各文字列をコピーする必要がないことにも注意してください。これが場合は、防御コピーの一部としてList<StringBuilder>、新しいリストと各要素の新しいコピーを作成する必要があります。ご覧のとおり、すべての状態が不変であると、生活はよりシンプルになります。

于 2012-08-17T06:21:00.723 に答える
3

finalポインタが別の参照を指すことができないことを意味します。例えば:

final Object obj = new Object();
obj = new Object(); //Invalid

ただしfinal、オブジェクトの変更を妨げることはありません。

obj.setWhatever("aaa"); //Perfectly valid

メンバーへのアクセスを制限していない場合は、誰でもオブジェクトを取得して変更できます。

例えば:yourClass.getObject().setWhatever("aaa").

防御的コピーとはgetObject()、オブジェクトを直接返すことはありませんが、オブジェクトのコピーを作成してから返すことを意味します。このように、呼び出し元が返されたオブジェクトを変更しても、クラスの元のメンバーは変更されません。

于 2012-08-17T06:17:25.197 に答える