研究ノート@EffectiveJava
記事の内容は、Joshua Bloch-Effective Java(3rd)-2018.chmという本からのものです。
第2章
オブジェクトの作成と登録解除
インスタンス化できないアイテム4には、プライベートコンストラクターが必要です
プライベートコンストラクターで非インスタンス化を強制する
静的メソッドと静的フィールドのセットのみを含むクラスを作成したい場合があります
このような業界での批判は、対象に関しては、頭脳なしで使用する人もいますが、効果的な用途があります。
- java.lang.Mathまたはjava.util.Arraysを使用して、プリミティブ値または配列を使用して関連するメソッドをグループ化できます
- また、java.util.Collectionsファイルを使用して、特定のインターフェースを実装するオブジェクトの静的メソッドをグループ化するために使用することもできます。
- または、これらのクラスはサブクラスに配置できないため、メソッドを最終クラスにグループ化するために使用できます。
- (Java8以降では、これらのメソッドを変更すれば、これらのメソッドをインターフェースに配置することもできます)
このようなユーティリティクラスは、インスタンス化されるようには設計されていません。この種の例は無意味です。
ただし、明示的なコンストラクターがない場合、コンパイラーは、パラメーターのないパブリックなデフォルトコンストラクターを提供します。
ユーザーにとって、このコンストラクターは他のコンストラクターと何ら変わりはありません
公開されたAPIでインスタンス化可能なクラスを誤って表示することは珍しくありません
クラスを抽象化してインスタンス化できないように強制しようとしても機能しません
クラスはサブクラスにすることができ、サブクラスはインスタンス化できます
さらに、クラスが継承用に設計されているとユーザーに誤解させます
ただし、インスタンス以外を確保するための簡単な使用法があります
デフォルトのコンストラクターは、クラスに明示的なコンストラクターがない場合にのみ生成されるため、
プライベートコンストラクターを含めることで、クラスをインスタンス化できないようにすることができます。
// Noninstantiable utility class
public class UtilityClass {
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
... // Remainder omitted
}
明示的なコンストラクターはプライベートであるため、クラス外からはアクセスできません
エラーAssertionErrorは厳密には必須ではありませんが、クラスからコンストラクターが誤って転送されるのを防ぐための保険メソッドを提供します
いかなる状況でもクラスがインスタンス化されないことを保証します
このイディオムは、コンストラクターが明示的に提供されており、まだ呼び出すことができないため、少し直感に反します。
したがって、上記の例のように、コメントを追加するのが賢明です
副作用として、このイディオムはクラスがサブクラス化されるのも防ぎます
(通常の状況では)すべてのコンストラクターは、明示的または暗黙的に親クラスコンストラクターを呼び出す必要があります(ただし、この場合)子クラスには、呼び出すためのアクセス可能な親クラスコンストラクターがありません