多くの Java 関連 API でデフォルトの引数なしコンストラクターが必要なのはなぜですか? 原則として、すべての Java Bean クラスまたはエンティティ クラス (JPA など)、または JAX-WS 実装クラスには、明示的な引数なしのコンストラクターが必要です。
Java がデフォルトで引数なしのコンストラクターを提供している場合、これらの標準のほとんどが明示的なコンストラクターを必要とするのはなぜですか?
多くの Java 関連 API でデフォルトの引数なしコンストラクターが必要なのはなぜですか? 原則として、すべての Java Bean クラスまたはエンティティ クラス (JPA など)、または JAX-WS 実装クラスには、明示的な引数なしのコンストラクターが必要です。
Java がデフォルトで引数なしのコンストラクターを提供している場合、これらの標準のほとんどが明示的なコンストラクターを必要とするのはなぜですか?
他のコンストラクターが定義されていない場合、Java はデフォルトの引数なしコンストラクターのみを提供します。したがって、他のコンストラクターがある場合は、引数なしのコンストラクターを自分で明示的に定義する必要があります。
これらのフレームワークは、リフレクション API を使用し、メソッド名を調べてプロパティの設定方法を決定します。コンストラクターの引数は、名前ではなく型によってのみ見つけることができるため、フレームワークがプロパティをコンストラクターの引数に確実に一致させる方法はありません。したがって、オブジェクトを作成するには引数なしのコンストラクターが必要であり、セッター メソッドを使用してデータを初期化できます。
@ConstructorProperties
一部のフレームワークは、代替としてサポートする場合があります。
nullary コンストラクターを必要とするフレームワークは、public
リフレクションを使用して型をインスタンス化するため、たとえばClass.newInstance()
.
この場合、デフォルトのコンストラクターが機能しない理由については、関連する JLS セクションを次に示します。
JLS 8.8.9 デフォルト コンストラクタ
a
class
にコンストラクター宣言が含まれていない場合、パラメーターをとらない既定のコンストラクターが自動的に提供されます。
class
が宣言されている場合public
、デフォルトのコンストラクターには暗黙的にアクセス修飾子が与えられますpublic
。- クラスが宣言されている場合
protected
、デフォルトのコンストラクターには暗黙的にアクセス修飾子が与えられますprotected
。- クラスが宣言されている場合
private
、デフォルトのコンストラクターには暗黙的にアクセス修飾子が与えられますprivate
。- それ以外の場合、既定のコンストラクターは、アクセス修飾子なしで暗黙的に既定のアクセスを持ちます。
したがって、public
クラスでは、デフォルトのコンストラクターが適切な可視性を持ちますが、それ以外の場合は明示的に可視性をpublic
提供する必要があります。
デフォルト以外の値を初期化するにはコンストラクターが必要であり、必要な副作用を含めることができます。
データ転送オブジェクトの最小限のコンストラクターを推奨するプログラミング スタイルを使用している場合、これは不要に思えるかもしれませんが、ライブラリーはコンストラクターのプログラミング スタイルを想定しないことを選択しています。
デフォルトのコンストラクターを想定しないライブラリを作成することはできますが、コンストラクターが行うことと行わないことについて想定する必要があります。つまり、私はそのようなライブラリを作成しましたが、コンストラクターが許可されていることを強制して、直接呼び出さないようにすることもできました。
他のコンストラクターが適用されない場合、Java は引数なしのコンストラクターのみを提供します。多くの Java API (JPA、シリアライゼーション、および外部表現からオブジェクトを構築するその他の多く) では、オブジェクトのデータ値を設定する前にオブジェクトのインスタンスが必要です。オブジェクトのインスタンス メンバーを通じて定義されます (例: readExternal(ObjectInput))。クラスにいくつかの引数を取るコンストラクターしかない場合、別の引数のないコンストラクターが定義されていない限り、ライブラリーがインスタンスを構築できない可能性があります。
これは特定のライブラリの実装者による設計上の選択であることは注目に値します。引数のないコンストラクタを持たないオブジェクトを外部化して再作成できる API/フレームワークを構築することは可能です (別のファクトリ クラスを定義することは1 つのアプローチ)。引数なしのコンストラクターを必要とするパターンは、Java シリアライゼーション (私が思うに) で最初に登場し、他のライブラリー (JPA など) で事実上の標準的なアプローチとして採用されました。このアプローチの弱点は、不変オブジェクトを使用できないことです。
2 つの理由: 1) 参照データ型のインスタンス データ フィールドが初期化されていない場合に NullPointerException を回避するため。明示的なコンストラクターを提供すると、宣言時に初期化されていない場合、そのようなデータ フィールドを初期化する機会が得られます。2) 引数なしのコンストラクターを使用したいユーザー向け。他のコンストラクターが存在する場合、これらは自動的に提供されません