構成ファイルから読み取ったインターフェイスをその実装にバインドして、IoCコンテナーにフィードできるようにしようとしています。これが私がやろうとしていることの大まかなものです:
public class PropertyImplementationBinder<T> {
// ...
public Class getInterfaceClass() {
return T.class; // OR Class<T>, note T is not newable
}
public Class getImplementationClass() {
return /* read config file to get implementation class */;
}
}
どういうわけかT.class
を取得することは可能ですか?
クラスをコンストラクターに明示的に渡す(そして自分で保存する)必要があります。
private final Class<T> clazz;
PropertyImplementationBinder(Class<T> clazz){
this.clazz = clazz;
}
public Class<T> getInterfaceClass() {
return clazz;
}
クラスのジェネリックスーパークラスの実際の型引数を取得できます。この ブログ投稿 は、些細な匿名の内部クラスを使用したちょっとしたトリックなど、これによって提示される可能性を探ります。直接引用するには:
JVMはジェネリッククラスのインスタンスの実際の型引数を追跡しませんが、の実際の型引数を追跡することがわかりました。 サブクラス ジェネリッククラスの。言い換えると、実行時の
new ArrayList<String>()
は実際には単なるnew ArrayList()
ですが、クラスがArrayList<String>
を拡張する場合、JVMはString
がList
の型パラメーターの実際の型引数。
広く受け入れられているものとは異なり、ほとんど知られていない型消去を回避できます。つまり、呼び出し先は、呼び出し中に使用された汎用パラメーターを知ることができます。
以下をご覧ください: TypeTokenを使用してジェネリックパラメーターを取得する
この記事では、このテクニックを使用したユーザーの体験についても説明しています。一言で言えば、私たちはフォールバックすることになりました...
従来の広く使用されている手法: "コンストラクターでクラス型を渡す"
ところで。 @Richard Gomesの記事にある静的メソッドgetTypeの例には、2つのエラーがあります。次のようになります。
static public Class<?> getType(final Class<?> klass, final int pos) {
// obtain anonymous, if any, class for 'this' instance
final Type superclass = klass.getGenericSuperclass();
// test if an anonymous class was employed during the call
if ( !(superclass instanceof ParameterizedType) ) {
throw new RuntimeException("This instance should belong to an anonymous class");
}
// obtain RTTI of all generic parameters
final Type[] types = ((ParameterizedType) superclass).getActualTypeArguments();
// test if enough generic parameters were passed
if ( pos >= types.length ) {
throw new RuntimeException(String.format("Could not find generic parameter #%d because only %d parameters were passed", pos, types.length));
}
if (!(types[pos] instanceof Class<?>)) {
throw new RuntimeException("Generic type is not a class but declaration definition(all you get is \"[T]\") " + types[pos]);
}
// return the type descriptor of the requested generic parameter
return (Class<?>) types[pos];
}
残念ながら、コードに明示的に含まれている場合は機能するため、まだ魔法の弾丸ではありません
getType(new SomeObject<String>(){}.class, 0) // you get String.class
しかし、あなたがこれを次のようなもので呼ぶなら
getType(new SomeObject<T>(){}.class, 0) // you get T as TypeVariable<D> and not actuall class of it
Tという名前を付けてください。