2011-12-22 16 views
1

リフレクションを使用して、指定されたクラス名の文字列でクラスオブジェクトをインスタンス化する必要があるテンプレートメソッドがあります。戻り値のクラスが型変数を使用するインタフェースの実装であるため、このケースは少し複雑です。私はクラス名の文字列とインターフェイスの型変数の型を渡して、クラスオブジェクトを作成したいと思います。ここでは例のメソッドシグネチャは次のとおりです。リフレクションを使用してオブジェクトを作成するテンプレートメソッドを作成する

<T> Class<? extends Foo<T>> 
createClassObject(String className, Class<T> classTypeVariable); 

は、それがどの警告や@SuppressWarningsの注釈のいずれかの使用法なしのJava 1.5でこのメソッドを実装することは可能ですか?

EDIT:トーマスコメントのおかげで、サンプルメソッドのシグネチャが編集されました。

+1

'classTypeVariable'は' T12'のインスタンスではなく 'Class 'でなければなりませんか? – Thomas

+0

Btw、あなたは本当に実行時にクラスを作成するか、単にそれを調べますか?または、そのクラスのインスタンス、つまりオブジェクトを作成しますか? – Thomas

+0

@Thomas、クラスオブジェクトであるClass.forName()の戻り値を使用します。 – jilt3d

答えて

3

いいえ、警告や@SuppressWarningsアノテーションの使用なしには達成できません。これは、Class.forName()がClassとして型指定されるためです。より具体的なもの(例えば、Class<? extends Foo<T>>の行に沿ったもの)にキャストしようとすると、タイプ消去に関する警告が表示されます。 Class.forName()。newInstance()をキャストしようとすると同じことが起こります。

つまり、この方法は@SuppressWarningsを積極的に使用するための最も重要な例です。このような場合、この注釈を使用する際に問題はありません。もちろん、Class.forName(className)Foo<T>に拡張されていることを確認するロジックを追加して、キャスティングが確実であることを確認することができます。このランタイムチェックはメソッドをより壊れにくくしないことに注意してください。メソッド内にClass.forName()呼び出しがあると、潜在的なランタイムタイプのエラーが発生しています。

+1

'Class.forName(className).asSubclass(String.class)'を実行することができる文字列クラスであれば、 'Class 'を 'Class.asSubclass()'を使ってより具体的にキャストすることが可能です。 。サブクラス( 'Foo')がパラメータ化されているため、この場合は機能しません。 –

+0

@ケビンK:それはまさに私がやろうとしていた! – jilt3d

1

返されるクラスがgeneric(Bar<T> extends Foo<T>またはその他のもの)であると想定されている場合、型システムは実行時にチェックする方法がないため、不可能であると確信していますClass.forName(...)が返されるクラスは、Class<Bar<U>>などとは対照的に、Class<Bar<T>>です。実際にはBar<...>のすべてのタイプを表す単一のClassオブジェクトがありますが、タイプシステムにはその表現がないため、Class<Bar<T>>Class<Bar<U>>は異なるタイプの完全に別々のオブジェクトです。)最も近いものは何かですあなたはそれがasSubclassチェックを行うには(この場合Iterable<T>で)Foo<T>に関する十分な情報を持っていることを考えることにコンパイラをだまして未チェックのキャストを使用し

<T> Class<? extends Iterable<T>> createClassObject 
     (final String className, final Class<T> clazz) throws Exception 
    { return Class.forName(className).asSubclass(getIterableTClass(clazz)); } 

@SuppressWarnings("unchecked") 
<T> Class<? extends Iterable<T>> getIterableTClass(final Class<T> clazz) 
    { return (Class<? extends Iterable<T>>)(Class<?>)Iterable.class; } 

:このように。

ただし、返されるクラスがでない場合は、(generic)(Bar extends Foo<String>またはその他のもの)と仮定されています。私は彼らが存在することを知っているが、それを扱う反射の部分をあまり扱っていない。私は彼らが実際にFoo<String>を拡張するかどうかを判断するためにBarの継承階層を十分に調べることを許可すると確信していますが、コンパイラが、そうした。

0

はいできます。 NetBeans IDE 7では、警告は表示されません。

修正:申し訳ありませんが、これは動作しません、クラス構成はありません。もちろん、ClassLoader、プロキシクラス、またはASMを使用することもできます。

public class Bar<T> extends Foo<T> { 
} 

本当に論理的でシンプルです。手掛かりはおそらく、チェーンされたnewInstance()を実行している可能性があります。

public <T> Class<? extends Foo<T>> createClassObject(String className, Class<T> classTypeVariable) { 
    try { 
     Class<? extends Class> resultType = Bar.class.getClass(); 
     return resultType.getConstructor(classTypeVariable).newInstance(); 
    } catch (InstantiationException ex) { 
     throw new IllegalStateException(ex); 
    } catch (IllegalAccessException ex) { 
     throw new IllegalStateException(ex); 
    } catch (IllegalArgumentException ex) { 
     throw new IllegalStateException(ex); 
    } catch (InvocationTargetException ex) { 
     throw new IllegalStateException(ex); 
    } catch (NoSuchMethodException ex) { 
     throw new IllegalStateException(ex); 
    } catch (SecurityException ex) { 
     throw new IllegalStateException(ex); 
    } 
} 
関連する問題