Effective Java第4条:私有コンストラクタによるインスタンス化不可能な能力の強化

1410 ワード

静的メソッドと静的ドメインのみを含むクラスを記述する必要がある場合があります.これらの類の名声はよくありません.一部の人はそれらを乱用して対象の角度から考えることを避けるためですが、それらにも確かに特有の用途があります.私たちはjavaでこの種類を利用することができます.lang.Mathまたはjava.util.Arrays方式では,基本タイプの値や配列タイプに関するメソッドを組織する.javaも使えますutil.Collections方式では、特定のインタフェースを実現するオブジェクト上の静的メソッド(工場メソッドを含む、第1条参照)を組織する.最後に、このクラスを利用してfinalクラス上のメソッドを組織し、クラスを拡張する代わりにすることもできる.
このようなツールクラス(utility class)はインスタンス化されるものではありません.インスタンスには意味がありません.ただし、明示的なコンストラクタが欠けている場合、コンパイラは自動的に公有的でパラメータのないデフォルトコンストラクタを提供します.(default constructor).ユーザーにとって、このコンストラクタは他のコンストラクタと何の違いもありません.発行されたAPIでは、無意識にインスタンス化されたクラスがよく見られます.
クラスを抽象クラスにすることによって,そのクラスをインスタンス化できないように強制しようとするのは無理である.このクラスは布団でクラス化することができ、サブクラスもインスタンス化することができる.このようにすると、継承のために設計されたものと勘違いすることもあります(第17条参照).しかし、クラスがインスタンス化されないことを保証する簡単な慣習的な使い方があります.クラスに明示的なコンストラクタが含まれていない場合にのみ、コンパイラはデフォルトのコンストラクタを生成するため、クラスにプライベートコンストラクタを含ませることはできません.
// Noninstantiable utility class
public class UtilityClass {
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
... // Remainder omitted
}

明示的なコンストラクタはプライベートなので、クラスの外部にアクセスすることはできません.AssertionErrorは絶対に必要ではありませんが、クラスの内部でコンストラクタを呼び出すのを避けることができます.クラスがインスタンス化されないことを保証します.この習慣の使い方は直感に反し、コンストラクタが呼び出せないように設計されているようだ.したがって、上記のようにコードにコメントを追加するのが賢明です.
この習慣の使い方にも副作用があり、一つのクラスを分類できない.すべてのコンストラクタは、サブクラスにアクセス可能なスーパークラスコンストラクタが呼び出されないように、明示的または暗黙的にスーパークラスコンストラクタを呼び出す必要があります.