0

Java でオブジェクトを不変にするために、クラスを final とマークし、そのすべての変数を final にし、setter と getter を提供しませんでした。これらは、オブジェクトが変更されないという十分な保証を提供しますか? 3 つすべてが必要ですか、それとも 3 つの条件のうち 2 つがあれば十分ですか?

4

5 に答える 5

6
public final class MyClass

不変性とは関係ありません。継承を許可しないだけです。

変数参照をマークするfinalだけでは十分ではなく、参照するすべてのオブジェクトも不変でなければなりません。

finalオブジェクトを不変にするのではなく、参照を不変にします。

private final List<String> strings = new ArrayList<String>();

stringsは依然として可変であり、への参照Listのみが不変です。List

次のようなことに注意してください。

Collections.unmodifiableList(strings);

Collections.unmodifiableList() JavaDocListは「変更不可能なビュー」を提供しますが、ラップされている元のリストへの外部参照によって基になるリストが変更されないことを保証するものではありません。リストの内容のディープ コピーを新しいリストに作成し、そのリストを でラップする必要がありunmodifiableます。

また、すべてのオブジェクトのすべてのインスタンスと、そのすべての子および子の子も不変でなければなりません。

于 2013-04-13T23:49:33.587 に答える
1

フィールドを最終としてマークすることは、言及されたセットから必要な唯一のオプションです。ゲッターを提供できますが、コレクションのような変更可能なサブオブジェクトには注意してください。Final は参照を不変にしますが、内容は不変にします。ゲッターを使用した便利なテクニックは、値が次のように変更可能な場合に防御的なコピーを作成することです。

public class ImmutableExample{

    private final int value1; // immutable
    private final List<Integer> value2; // contents will not be immutable

    public ImmutableExample(...){...} // be careful here to copy the collection as you want to disalow any outside modification.

    public int getValue1(){
        return value1;
    }

    public List<Integer> getValue2(){
        return Collections.unmodifiableList(value2);
    }
}

もう 1 つのオプションは、不変オブジェクトと変更不可能なコレクションで説明したように、不変コレクションを含む Google Guavaコレクションを使用することです。これらは非常に簡単な不変クラスになります:

public class ImmutableExample{

    private final int value1; // immutable
    private final ImmutableList<Integer> value2; // immutable

    public ImmutableExample(...){...}

    public int getValue1(){
        return value1;
    }

    public List<Integer> getValue2(){
        return value2;
    }
}
于 2013-04-13T23:53:23.807 に答える
0

Marking your class as final you're only telling that no one can subclass it.

That said, marking your variables as final would be enough, as long as your class had only 'primitive' attributes. It's ok (and encouraged) to keep the getters, however, you also may want remove the setters, since while you don't want any external class to mess around with your variables, setters won't be needed.

于 2013-04-13T23:45:30.953 に答える
0

すべての変数をプライベートに設定し、ゲッターのみを提供する方が自然です。finalその後、不要なやり過ぎであるクラスを設定する必要はありません。

フィールドがコレクションなどの非最終オブジェクト自体である場合は、さらに検討する必要があります。これらのコピーのみを保存してください。

于 2013-04-14T00:06:29.523 に答える