Effective Javaの独自解釈です。
第3版の項目4について、自分なりにコード書いたりして解釈してみました。
結論
staticメンバしか持たないクラスには、実行時例外を出すprivateコンストラクタを用意しよう。
説明
例えば共通の処理だけを集めたユーティリティクラス(以下、Utilクラス)はstaticメソッド、static変数のみを持ち、インスタンス化を前提としていない。
一般にpublicなUtilクラスは、コンストラクタを定義しないとpublicなデフォルトコンストラクタが用意されるため、外部のクラスで無駄にインスタンス化されてしまう懸念が生じる。
明示的にprivateコンストラクタを定義することで、Utilクラス外でのコンストラクタ呼び出しを防ぐことができる。
また、コンストラクタに例外出力処理を入れることで、Utilクラス内でのコンストラクタ呼び出しをエラーとすることができる。
※Utilクラスそもそもいらない論はここでは無視。
コンストラクタ定義なしコード(ダメな例)
Utilクラス
public class SampleUtil {
public static final String HOGE = "hoge";
public static String fugaMethod() {
return "fuga";
}
}
呼び出し側クラス
public class SampleService {
public String sampleMethod() {
// 無駄にインスタンス化
SampleUtil sampleUtil = new SampleUtil();
return sampleUtil.fugaMethod();
}
}
呼び出し側クラスでインスタンスを作っています。fugaMethod()
はstaticメソッドなので、インスタンス化するのは無駄です。
privateコンストラクタ定義ありコード(良い例)
Utilクラス
public class SampleUtil {
// privateかつ実行時例外を出力するコンストラクタを定義
private SampleUtil() {
throw new IllegalStateException("Util instance construction is not allowed.");
}
public static final String HOGE = "hoge";
public static String fugaMethod() {
return "fuga";
}
}
呼び出し側クラス
public class SampleService {
public String sampleMethod() {
return SampleUtil.fugaMethod();
}
}
コンストラクタがprivateなので、別のクラスではそもそもインスタンス化できません。
また、仮にUtilクラス内でコンストラクタが呼ばれたとしても、例外が出力されるためインスタンスが作られることはありません。コンストラクタを呼ぶようなコードが書かれている場合、それはプログラミングエラーなので、実行時例外を出すようにしましょう。
※コンパイルは通るので、プログラミングエラー自体を防ぐことはできません。