現在、Joshua Bloch の Effective Java 第 2 版を読んでいるので、しばらくはこの本の読書メモを書いていく。
項目 1: コンストラクタの代わりに static ファクトリーメソッドを検討する
インスタンスを生成するためには、コンストラクタを使うのが普通の方法である。 この項目では、コンストラクタの代わりに static ファクトリーメソッドを使ってオブジェクトを生成することの利点と欠点について述べてられている。
static ファクトリーメソッドとは、クラスのインスタンスを返す static メソッドのことである。
例えば、Integer.valueOf
は基本データ型 int
の変数を引数に取り、基本データクラスを返す static ファクトリーメソッドである。
public class Foo { public static void main(String[] args) { Integer i = Integer.valueOf(1); // Integer オブジェクトを生成 } }
static ファクトリーメソッドの利点
コンストラクタと比較して、static ファクトリーメソッドを使うことの利点は主に以下の 4 項目による。
- メソッドなので名前を付けられる
- static ファクトリーメソッドが呼ばれるたびに新しいインスタンスを生成する必要がな
- static ファクトリーメソッドの戻り値型のサブタイプを返せる
- パラメータ化された型(ジェネリクス)のインスタンス生成を省力化できる
1 は、メソッドが名前を持つことで、どのような用途か理解しやすくなるということである。また、同じシグニチャでありながら別の処理を行うコンストラクタは作れないが、static ファクトリーメソッドなら可能である。
2 は、インスタンスの生成を制御して、static フィールドに保持したり、Singleton のように数を調節できるということである(インスタンス制御)。
3 は、java.util.Collections
の static ファクトリーメソッド群が例として挙げられる。 これらの static ファクトリーメソッドの戻り値型は List<E>
や Map<K, V>
などのインタフェースになっており、List<Integer> list = Collections.emptyList();
のように、それらの型の変数で生成したオブジェクトを受け取る。 しかし、実際は、それらのインタフェースは何らかの型で実装されている。 つまり、インタフェースと実装の分離により、実装の詳細が隠蔽されている。 これにより、クラスの提供者は利用者に知られずに生成するオブジェクトの変更などを行える。 この点で、static ファクトリーメソッドを使わない場合と比較して、拡張性に富む。
4 は、型パラメータの指定の煩雑さを軽減できるということである。つまり、
Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
より、例えば HashMap が newInstance() という static ファクトリーメソッドを持っていたとして、
Map<Integer, List<Integer>> map = HashMap.newInstance();
とする方が楽だということである。 実は、Java 7 以降では、以上の方法を使わずとも、ダイヤモンド構文でコンパイラが型推定してくれる。
Map<Integer, List<Integer>> map = new HashMap<>();
static ファクトリーメソッドの欠点
上述した利点の一方で、static ファクトリーメソッドには以下の欠点がある。
public
/protected
のコンストラクタを持たないクラスのサブクラスを作れない- 他の static メソッドと混同してしまう
1 は、public
/ protected
コンストラクタを持たないクラスのサブクラスから、そのようなクラスのコンストラクタにアクセスできないことによる。
2 は、static ファクトリーメソッドへの命名方法を標準的な方法に統一することで、ある程度解決できる問題である。 一般的には、それぞれのメソッドの性質に応じて、以下の名前を付けることが多い。
valueOf
,of
- 引数と同じ意味を表すオブジェクトを返すメソッド
getInstance
- 引数から別の意味を持つオブジェクトを返すメソッド。インスタンスを毎回新しく生成するとは限らない
newInstance
- getInstance と違って、必ず新しいインスタンスを生成する
get
Type,new
TypegetInstance
,newInstance
と同じ働きだが、型 Type のオブジェクトを返す
参考文献
EFFECTIVE JAVA 第2版 (The Java Series)
- 作者: Joshua Bloch,柴田芳樹
- 出版社/メーカー: 丸善出版
- 発売日: 2014/03/11
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (12件) を見る