effective java 輪読会 第2章 項目1,2,3,4
DESCRIPTION
TRANSCRIPT
Effective Java 輪読会
2013/11/27開発部 田中
第2章 オブジェクトの生成と消滅(前半)
• 項目1– コンストラクタの代わりに static ファクトリー
メソッドを検討する
メリット
名前を付けられる• 可読性の向上– クラスから生成されるインスタンスが特殊な
場合Ex. BigInteger.probablePrime
– 同じシグニチャを持つ複数のコンストラクタを定義する場合
インスタンスの生成は強制でない
• static フィールドを返すEx. Boolean.valueOf(boolean)
• 「シングルトン」、「インスタンス化不可能」であることを保証できる
Cf. 「インスタンス制御」されている → 項目3、項目4、項目15
サブタイプのオブジェクトを返せる
• ユーティリティクラスに、戻り値がインターフェースであるメソッドを定義する– 実際の戻り値のクラスを Public で定義する必
要がなくなる(実装クラスを隠蔽)
型パラメータの冗長さを低減
Map<String, List<String>> map = new HashMap<String, List<String>>();
public static <K, V> HashMap<K, V> newInstance() { return new HashMap<K, V>();}
Map<String, List<String>> map = HashMap.newInstance();
デメリット
サブクラスを作れない(?)• 意図してインスタンス化不可能にする– コンストラクタを private にする
他の static メソッドと区別がつかない
• 命名規約で回避• valueOf()• getInstance()• newInstance()
まとめ• インスタンス化の方法として、状況に応じ
て static ファクトリーメソッドを用いるべきである
• 項目2– 数多くのコンストラクタパラメータに直面し
た時にはビルダーを検討する
テレスコーピングコンストラクタ
• 必須フィールドとオプションフィールド– 必須フィールドのコンストラクタに、オプ
ションフィールドのコンストラクタを1つずつ追加する
→ 使いづらく、読みにくい
JavaBeans
• パラメータなしのコンストラクタで初期化した後、セッターでフィールドに値をセットしていく
→ 不整合な状態になるかもしれない→ final フィールドにできない
ビルダー
• build() で目的のクラスのインスタンスを生成
• 目的のクラスのフィールドは全てに final属性を付与できる
• 読みやすい(宣言的?)
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8). calories(100).sodium(35).build();
まとめ• 多くのパラメータを持つクラスの初期化
方法としてビルダーパターンは有効である• ただし、ビルダーを生成するコストが問
題になる可能性がある
• 項目3– private のコンストラクタか enum 型でシング
ルトン特性を強制する
クラスをシングルトンにする方法
public final フィールド
• コンストラクタを private にすることで、オブジェクトの生成を 1 回のみに強制する
public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() { ... }
...}
static ファクトリーメソッド
• インスタンスは private static final フィールドで一度のみ初期化
• ファクトリーメソッドで参照するINSTANCE は常に同一インスタンス
public class Elvis { private static final Elvis INSTANCE = new Elvis(); private Elvis(); public static Elvis getInstance() { return INSTANCE; }
...}
単一要素の enum 型public enum Elvis { INSTANCE;
...}
• 項目4– private のコンストラクタでインスタンス化不
可能を強制する
private コンストラクタ
• デフォルトコンストラクタを抑制• サブクラス化も不可能
public class UtilityClass {
private UtilityClass() { throw new AssertionError(); }
...}