プライベートT_memberを含むJavaクラスがパラメータ化されているとします。T _memberを既知のタイプT固有の値(整数の場合は-1、浮動小数点の場合はFloat.MAX_VALUEなど)に初期化するデフォルトのコンストラクター(引数なし)を作成したいと思います。それは可能ですか?新しいT()を試しましたが、コンパイラーはそれを好みません。または、何もしません。デフォルトのコンストラクターが呼び出されることが保証されていますか?
4 に答える
型消去のため、実行時に「Tはありません」。
これを回避する方法は、次のように、のインスタンスをClass<T>
コンストラクターに渡すことです。
public class MyClass<T> {
T _member;
public MyClass(Class<T> clazz) {
_member = clazz.newInstance(); // catch or throw exceptions etc
}
}
ところで、これは「Tで何かをする」という問題を解決するための非常に一般的なコードパターンです。
デフォルトのコンストラクターT
さえあることを保証する方法がないので、それは直接可能ではありません。newInstance
ただし、リフレクションを使用してそれを行うこともできます。スローされる可能性のある例外を必ずキャッチしてください。
public class MyClass<T> {
private T _member;
public MyClass(Class<T> cls) {
try {
_member = cls.newInstance();
} catch (InstantiationException e) {
// There is no valid no-args constructor.
}
}
}
イニシャライザ式のないJavaのすべてのフィールドは、既知のデフォルト値に自動的に初期化されます。そして、はい、この場合、それはタイプT-の既知の値ですnull
。
実際、これを行う方法があります。ここに、関連するSOの質問に答えるためのリンクがあります。
したがって、実際、実行時にジェネリックメンバーのクラスを取得する可能性があるかどうかの主な質問はありますか?はい、あります-反射を使用します。
約1年前にその答えに出くわしたとき、私はそれをテストし、反射をもう少し調査しました。実際、そのままでは機能しない場合がいくつかありますが(継承の場合に注意してください)、一般的に、これが不可能であると主張するのは誤りです。
ただし、このようにすることは強くお勧めしません。
編集。驚いたことに、私はその答えの下に自分のコメントを見つけました:)そして次のコメントには、ジェネリックスの反省に関する元の記事への著者によるリンクがあります。