これを尋ねなければならないのはまったくばかげていますが、なぜ次のJavaコードがコンパイルされないのか理解できませんでした:
void <T> doSomething(List<T> items) {
Class<? extends T> clazz = items.get(0).getClass();
...
}
Java docから:
実際の結果タイプはClass <? | X |>を拡張します| X | getClassが呼び出される式の静的タイプの消去です。たとえば、次のコードではキャストは必要ありません。
数値n = 0;クラス<? Number> c = n.getClass();を拡張します。
編集:
見つかりました この素敵な説明 静的型の消去消去の意味。
スーパータイプトークン と呼ばれる、サブクラスを使用してジェネリック型情報を保持する方法があります。現在削除された回答は、Guavaライブラリにこれを悪用するための 便利なユーティリティ があることを指摘しました。
以下は、ジェネリック型をリフレクティブに抽出する際の 素晴らしい記事 といいます GenTyRef と呼ばれる素敵なライブラリです。
GenTyRefをフォークして、AnnotatedType
sの操作のサポートを追加しました(Java 8で導入)。これは GenAnTyRef と呼ばれます(Maven Centralにあります)。
items.get(0)
の静的タイプの消去はObject
です(T
はコンパイル中に消去されるため)。
したがって、items.get(0).getClass()
はClass<? extends Object>
ではなくClass<? extends T>
を返します。これは、試行した割り当てが失敗した理由を説明しています。
これはコンパイルを渡します:
Class<? extends Object> clazz = items.get(0).getClass();
ジェネリックパラメーターのClass
をそのメソッドが認識できるようにする場合は、追加の引数として渡すことができます。
void doSomething(List<T> items, Class<T> clazz) {
}
まず、メソッドの型パラメーターとしてTを定義する必要があります:<T> void doSomething
。次に、Class<? extends T>
へのキャストが必要です。だからこれはあなたが一緒にする方法です:
<T> void doSomething(List<T> items) {
Class<? extends T> clazz = (Class<? extends T>) items.get(0).getClass();
...
}