2017-06-12 11 views
4

私は次のようなクラスがありますクラス<T>を実行時にクラス<T extends Foo>のように動作させるにはどうすればよいですか?

class FooClassAnalyser<T extends Foo> extends ClassAnalyser<T> 

ClassAnalyserは、具体的な実装の数の抽象基底クラスであり、FooClassAnalyserTFooを拡張する場合に特化しています具体的な実装であるが)。それはこのようになりますコンストラクタがあります別のクラスにおいて

FooClassAnalyser(Class<T> classToAnalyse) 

を、私はclassToAnalyseの種類に応じて適切なコンストラクタを呼び出しClassAnalyserのための静的なファクトリメソッドを持っている:

static <U> ClassAnalyser<U> constructClassAnalyser(Class<U> classToAnalyse) 

機能私は、U instanceof Fooかどうかを確認し、FooClassAnalyserを作成して返します。

しかし、私はこれをJavaの型システム内に収める方法を見つけることができません。タイプ消去とは、Uで直接賢明なことを行うことはできないということです。

if (Foo.class.isAssignableFrom(classToAnalyse)) 

私の問題はinstanceofとは違って、これは「instanceofの反射を経て」には見えないということです。しかし、我々は引数が、それを可能にするようにclassToAnalyseを渡すことは、リフレクションを使用して経由U instanceof FooかどうかをテストしますJavaの型システム。特に、classToAnalyseが実際にClass<U extends Foo>であることをJavaが知らないため、FooClassAnalyserのコンストラクタへの引数として直接classToAnalyseを渡すと型の不一致が発生します。

私がこれまでに見つけた最良の解決策はclassToAnalyseClass<? extends Foo>を作るために未チェックのキャストを使用することです(それが確認さ実際ですが、Javaの気づいていないことが確認されていますということ)。少なくともそれをnew FooClassAnalyserの引数として渡して、FooClassAnalyser<?>オブジェクトを返すことが可能です。しかし、この問題は、ClassAnalyser<U>に変換されません。なぜなら、Javaでは、classToAnalyseに汎用バインディングが異なることを認識しないため、Classオブジェクトがまだ同じオブジェクトであるという事実は変わりませんしたがって、依然としてClass<U>である)。言い換えれば、Javaが認識できるすべてのFooClassAnalyser<?>もまたFooClassAnalyser<U>であるため、変換後に別のチェックされていないキャストが必要です。結果はコンパイルされて実行されるコードですが、型の安全性に関する多数の警告があります。

私が試みた他の多くのものは、構文エラーです(たとえば、Class<U extends Foo>の変数は直接宣言できません; Javaでは正しく解析されません)。私は実際にはいずれの時点でもタイプUのオブジェクトを持っていないことに注意してください。私はクラス自体を分析しようとしているので、作業するオブジェクトはClass<U>しかありません。

タイプセーフな方法でこのようなコードを書くことは可能ですか?

+1

価値があることは、私があなたがすでにやっているもの(チェックされていないキャストで)よりもうまくいくとは思わない。 Javaのジェネリックで少し前進したときにはいつも辛辣になってしまいます。 – kaqqao

+1

注釈として、 'Class <? 'へのチェックされていないキャストを使う必要はありません。 Foo> 'を拡張します。 ['clazz.asSubclass(Foo.class)'](http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#asSubclass-java.lang.Class- )。 – Radiodef

+0

@Radiodef:はい、 'clazz.asSubclass(Foo.class)'は 'Class <? 'Foo>は' 'についての知識を失ってしまいました。あなたは、 'FooClassAnalyser <? Fooを安全に警告なしで拡張しますが、ClassAnalyser '... – Holger

答えて

0

私の問題は、instanceofとは異なり、この「インスタンス反映」はJavaのタイプシステムには見えません。特に、classToAnalyseが実際にClass<U extends Foo>であることをJavaが知らないため、FooClassAnalyserのコンストラクタへの引数として直接classToAnalyseを渡すと型の不一致が発生します。

これは、Class<U>constructClassAnalyserに渡す限り発生します。あなたは多くのコードを私たちに提供していないので、私はあなたに明白な解決策を書くことはできません。しかし、UClass<U>の代わりにconstructClassAnalyserに渡す方法を見つけることができれば、もっと簡単になります。

static <U> ClassAnalyser<U> constructClassAnalyser(U objectToAnalyse)

そのクラスをチェックするには、objectToAnalyse#getClassを使用することができます。 instanceofを使用してU extends Fooを確認し、objectToAnalyse instanceof Footrueを返す場合は、必要に応じてそれぞれのクラスにキャストしてください。

+0

'ClassAnalyser'の全体点はクラスを解析することです。必ずしもそのクラスのオブジェクトを利用できるとは限りません。だから、この解決法はうまくいかず、これは本当に質問に答えません。 (私たちは、あなたが取り払うことができるか見るために非常に簡単になるだろうが、しかし、私は、あなたが私の現在のソリューションにおける第二未チェックのキャストを取り除くことができると確信していない、使用可能なクラスのオブジェクトを持っていた場合でも、最初に。 – smithaiw

+0

クラスを持っているなら、 'Class#newInstance'を使ってそのクラスの新しいインスタンスを作成してください。 –

+0

クラスにはアクセス可能なコンストラクタが必要で、コンストラクタに適切な引数が必要です。さらに、コンストラクタには副作用があるかもしれません。 (私はまだそれが最初の問題を解決する方法はまだ分かりません) – smithaiw

関連する問題