私は最近、 Netflix オープンソース プロジェクトの 1 つを経験していました。
そこで、最終クラスとプライベートコンストラクターの両方の使用を見つけました。私はそれを十分に認識しています
- final は継承を避けることです
- private は、インスタンス化を許可しないことです
しかし、なぜ両方が一緒に使用されているのか知りたいだけです。メソッドは静的ですが、インスタンス化せずに使用できますが、その背後にある設計原理を知りたいと思っています。
私は最近、 Netflix オープンソース プロジェクトの 1 つを経験していました。
そこで、最終クラスとプライベートコンストラクターの両方の使用を見つけました。私はそれを十分に認識しています
しかし、なぜ両方が一緒に使用されているのか知りたいだけです。メソッドは静的ですが、インスタンス化せずに使用できますが、その背後にある設計原理を知りたいと思っています。
このコードを使用すると、この機能が得られます
extends
誰にもあなたのクラスのサブクラス化 ( ) を許可しないこの場合、インスタンスを取得するためのシングルトン パターンが見当たらないので、私見ですが、Netflix API のヘルパー/ユーティリティ クラスを探しています。そこでは、開発者チームがいくつかの標準的な手法を使用して、ユーザーが確実にクラスを使用できるようにしました。正しい方法:
StaticFinalClassExample.methodYouWantToCall();
また、リンクしたクラスを見てください:
/**
* This class consists exclusively of static methods that help verify the compliance of OP1A-conformant....
*/
と:
//to prevent instantiation
private IMFConstraints()
{}
さらに詳しい情報が必要な場合はItem 4
、Joshua Bloch の「Effective Java (2nd Edition)」を参照してください。
項目 4: プライベート コンストラクターで非インスタンス化を強制する
静的メソッドと静的フィールドをグループ化しただけのクラスを書きたい場合があります。このようなクラスは、オブジェクトの観点から考えるのを避けるために悪用する人がいるため、悪い評判を得ていますが、有効な用途があります。
java.lang.Math
これらは、またはの方法で、プリミティブ値または配列に関連するメソッドをグループ化するために使用できますjava.util.Arrays
。- また、ファクトリ メソッド (項目 1) を含む、特定のインターフェイスを実装するオブジェクトの静的メソッドを のようにグループ化するためにも使用できます
java.util.Collections
。final
最後に、クラスを拡張する代わりに、クラスのメソッドをグループ化するために使用できます。このようなユーティリティ クラスは、インスタンス化するようには設計されていません。インスタンスは無意味です。ただし、明示的なコンストラクターがない場合、コンパイラーは、パラメーターなしのパブリックな既定のコンストラクターを提供します。ユーザーにとって、このコンストラクターは他のコンストラクターと区別できません。公開された API で意図せずにインスタンス化可能なクラスを目にすることは珍しくありません。
クラスを抽象化して非インスタンス化を強制しようとしてもうまくいきません。クラスをサブクラス化し、サブクラスをインスタンス化できます。さらに、クラスが継承用に設計されているとユーザーを誤解させます (項目 17)。
ただし、インスタンス化できないことを保証するための簡単なイディオムがあります。既定のコンストラクターは、クラスに明示的なコンストラクターが含まれていない場合にのみ生成されるため、プライベート コンストラクターを含めることでクラスをインスタンス化できないようにすることができます。
そのクラスはstatic
いわゆる「ユーティリティ」メソッドで構成されているため、そのインスタンスは必要ありません。さらに、そのインスタンスを取得しようとするのは間違っています。クラスは final であるため、クライアント開発者は、元のクラスの意図に反するため、クラスを拡張するオプションがありません。
プライベート コンストラクターには基本的に 2 つの用途があります。作成を制限したいクラスの場合 (たとえば、大量のリソースが必要な場合) にインスタンス化を厳密に制御するためです。この最初のケースではstatic
、クライアントのオブジェクトを作成するファクトリ メソッドを提供する必要があります。すなわち:
public static IMFConstraints getInstance()
もう 1 つのケースは、インスタンスを作成することが決して有効でない場合です。その場合、static
クラス自体で呼び出されるメソッドを提供します。すなわち:
public static void checkIMFCompliance(List<PartitionPack> partitionPacks)
上記のメソッドを次のように呼び出します。
// your cool client code here...
IMFConstraints.checkIMFCompliance(myPartitionPacks);
// more of your awesome code...
リンクしたクラスは後者のケースです。