項目 14: 可変性を最小限にする
この項目では、不変クラスの作り方に関して説明されている。
不変クラスは、生成したインスタンスの状態を変更できないようなクラスのことである。
String
, 基本データクラス(BigInteger
なども)は不変クラスである。
例えば、
String str = "foobar";
のように String
型のインスタンス str
は、文字列 "foobar"
を状態として持っているといえる。
str
が持つ文字列 "foobar"
を変更して、新たな文字列を持たせることはできない。
不変クラスの利点
生成時からの状態を保ち、後から状態を変更できない不変クラスには、以下のような利点がある。
- 単純で扱いやすい
- スレッドセーフである
- 防御的コピーが必要ない
- 複数のオブジェクト間で状態を共有できる
- マップやセットなど、他のオブジェクトで利用しやすい
不変クラスの欠点
個々の異なる状態に対して、異なるオブジェクトを生成する必要があることが欠点である。 例えば、以下のような場合を考える。
String str1 = "a...(100個続く)...a"; String str2 = "a...(100個続く)...b";
このとき、一文字違いの str1
と str2
はそれぞれ異なるインスタンスとなる。
クラスを不変にするための五か条
- オブジェクトの状態を変更できるメソッドを提供しない
- いわゆる setter など。このようなメソッドはミューテータと呼ばれる
- クラスを拡張できないようにする
- サブクラスで不変性を破られることを防ぐ
- すべてのフィールドを
final
にする - すべてのフィールドを
private
にする - 可変オブジェクトを持つ場合、その不変クラスだけがアクセスできるようにする
- クライアントの勝手な初期化、オブジェクト参照を返すメソッドはダメ
ここで、2 を実現する方法は 2 通りある。
一つ目は、単純にクラスに final
を付け、拡張を禁止する方法である。
二つ目は、コンストラクタを private
かパッケージプライベートにして、コンストラクタからオブジェクトを生成できないようにし、static ファクトリーメソッドを持たせる方法である。
項目 1 での議論より、二つ目の方がより柔軟である。
参考文献
EFFECTIVE JAVA 第2版 (The Java Series)
- 作者: Joshua Bloch,柴田芳樹
- 出版社/メーカー: 丸善出版
- 発売日: 2014/03/11
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (12件) を見る