次のような状況があります。
クラスには汎用フィールドが含まれています。実行時にT
のインスタンスでフィールドをインスタンス化することは可能ですか?Javaのリフレクションジェネリックス - コンパイル時にパラメータを渡してキャストしますか?
class Root<T>{
T var;
Root(){
//instantiate var with an instance of T here
}
}
次のような状況があります。
クラスには汎用フィールドが含まれています。実行時にT
のインスタンスでフィールドをインスタンス化することは可能ですか?Javaのリフレクションジェネリックス - コンパイル時にパラメータを渡してキャストしますか?
class Root<T>{
T var;
Root(){
//instantiate var with an instance of T here
}
}
Root<T>
に拡張されたクラスがあり、タイプパラメータがextends
句に設定されている場合は、getGenericSuperclass()を使用してそれを調べることができます。例えば、Guice uses this approachは、注入されたクラスに型パラメータ情報を提供します。
それ以外の場合は、Class<T>
インスタンスをコンストラクタパラメータとして渡して使用することをお勧めします。これは、クラスの各インスタンス化のためにもう少し定型的なものですが、より簡単なコードになります。
号
Javaは型消去を使用するため、一般的なパラメータは、実行時に存在していません。
実行時にT
のインスタンスが指定されていない限り、答えはjava type erasureのため、いいえです。実行時にTは実際にObjectに置き換えられ、必要な情報は存在しません。これは、List.toArrayのような関数では、型付きの結果を受け取るために型付きの配列を渡す必要があるからです。
本当にこの機能が必要な場合は、コンストラクタの型を渡す必要があります。このよう
:これは、リフレクション経由でインスタンスを作成します
class Root<T> {
private T var;
public Root(Class<T> type) {
var = type.newInstance();
}
}
。渡されたクラスにデフォルトコンストラクタがある場合にのみ機能します。それ以外の場合は、例を拡張する必要があります。
コンパイル時に消去されるため、T
のタイプを実行時に知る方法はありません。
ただし、Class<T>
のコンストラクタに新しいパラメータを追加できます。コンパイラは、渡されたオブジェクトがRoot
インスタンスに対して指定したT
タイプに対応するClass
インスタンスであることを確認します。あなたのコンストラクタでは、あなたは、新しいTのインスタンスを作成するためにリフレクションを使用することができます。
class Root<T> {
T var;
public Root(Class<T> klass) {
var = klass.newInstance();
}
}
これはあなたのT
タイプがデフォルトコンストラクタを持って想定します。
+1、または生成されたファクトリインターフェイスのインスタンスを取り込むだけです。 –