1. ホーム

[解決済み】Java:ジェネリック型からクラスリテラルを取得するにはどうすればよいですか?

2022-04-04 15:35:25

質問

一般的には、このようにクラスリテラルを使うことが多いようですね。

Class<Foo> cls = Foo.class;

しかし、型が一般的なもの、例えばListの場合はどうでしょうか?これは問題なく動作しますが、Listはパラメータ化されるべきなので、警告が発生します。

Class<List> cls = List.class

では、なぜ <?> ? さて、これでは型の不一致エラーが発生します。

Class<List<?>> cls = List.class

こんな感じでうまくいくと思ったのですが、これは単なる構文エラーです。

Class<List<Foo>> cls = List<Foo>.class

どうすれば Class<List<Foo>> は、クラス・リテラルを使用するなどして、静的に使用できますか?

I かもしれない 使用 @SuppressWarnings("unchecked") を使えば、最初の例でパラメータ化されていないListの使用によって引き起こされる警告を取り除くことができます。 Class<List> cls = List.class ということなのでしょうが、私はそうしたくないのです。

何か提案はありますか?

解決方法は?

が原因でできません。 タイプ・イレーズ .

Javaジェネリックスは、オブジェクトキャストのための構文上の糖分に過ぎません。実証するために

List<Integer> list1 = new ArrayList<Integer>();
List<String> list2 = (List<String>)list1;
list2.add("foo"); // perfectly legal

一般的な型情報が実行時に保持される唯一の例として Field.getGenericType() もしリフレクションによってクラスのメンバに問い合わせるなら。

これらのことは、なぜ Object.getClass() にはこのような署名があります。

public final native Class<?> getClass();

重要なのは Class<?> .

別の言い方をすれば Java Generics FAQ :

具体的なパラメタライズド型にクラス リテラルがないのはなぜですか?

パラメータ化された型は正確な実行時型表現を持っていないため。

クラスリテラルは Class オブジェクトは、与えられた型を表します。 たとえば、クラス リテラルの String.classClass オブジェクトを表します。 String と同じであり Class オブジェクトが返されます。 メソッド getClass を呼び出すと String オブジェクトを作成します。クラスリテラルは 実行時の型チェックに使用され を使用します。

パラメータ化された型は、その型 に変換されたときに バイトコードでコンパイルされます。 型消去と呼ばれる処理です。そのため 型消去の副作用として、すべての 汎用型のインスタンス化は 同じ実行時表現であること。 すなわち、対応する生の 型があります。 言い換えれば,パラメータ化された は型表現を持っていません。 である。したがって クラスリテラルを形成する意味がない のような List<String>.class , List<Long>.classList<?>.class がないため、このような Class オブジェクトが存在します。 生の型である List には Class オブジェクトは、そのランタイムを表す タイプになります。と呼ばれる。 List.class .