Java でオブジェクトを不変にするために、クラスを final とマークし、そのすべての変数を final にし、setter と getter を提供しませんでした。これらは、オブジェクトが変更されないという十分な保証を提供しますか? 3 つすべてが必要ですか、それとも 3 つの条件のうち 2 つがあれば十分ですか?
5 に答える
public final class MyClass
不変性とは関係ありません。継承を許可しないだけです。
変数参照をマークするfinal
だけでは十分ではなく、参照するすべてのオブジェクトも不変でなければなりません。
final
オブジェクトを不変にするのではなく、参照を不変にします。
private final List<String> strings = new ArrayList<String>();
strings
は依然として可変であり、への参照List
のみが不変です。List
次のようなことに注意してください。
Collections.unmodifiableList(strings);
Collections.unmodifiableList()
JavaDocList
は「変更不可能なビュー」を提供しますが、ラップされている元のリストへの外部参照によって基になるリストが変更されないことを保証するものではありません。リストの内容のディープ コピーを新しいリストに作成し、そのリストを でラップする必要がありunmodifiable
ます。
また、すべてのオブジェクトのすべてのインスタンスと、そのすべての子および子の子も不変でなければなりません。
フィールドを最終としてマークすることは、言及されたセットから必要な唯一のオプションです。ゲッターを提供できますが、コレクションのような変更可能なサブオブジェクトには注意してください。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;
}
}
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.
すべての変数をプライベートに設定し、ゲッターのみを提供する方が自然です。final
その後、不要なやり過ぎであるクラスを設定する必要はありません。
フィールドがコレクションなどの非最終オブジェクト自体である場合は、さらに検討する必要があります。これらのコピーのみを保存してください。