0

次のコード:

public static void main(String args[]) throws NoSuchFieldException {
    List<Integer> li = new ArrayList<Integer>();
    ParameterizedType apType = (ParameterizedType) li.getClass().getGenericSuperclass();
    Type[] typeArguments = apType.getActualTypeArguments();
    int _i = 0;
    for (Type type : typeArguments) {
        System.out.format("parameterized type %d is: %s", ++_i, type);
    }
}

生成:

parameterized type 1 is: E
  1. Eが型パラメーター名であることを考えると、これは Type Erasure の影響によるものであり、「不明」と解釈されるべきであるということを正しく理解していますか?
  2. 「E」という名前を特別に解釈しなければならないのは奇妙に思えます (さらに存在する場合は「S」、「U」などもあると思います)。クラス「E」の場合はどうなりますか? さらに、メソッド名は get_Actual_TypeArgumentsです。変数のように型パラメーターがプレースホルダーとして機能することを考えると、メソッドが変数の名前を返さなければならないのは非常に奇妙だと思います。ここで何か不足していますか?
  3. また、スーパークラスをParameterizedTypeにキャストできるのに、クラス自体をキャストできない理由も明確ではありません。li.getClass()の結果をParameterizedTypeとしてキャストしようとすると、次のコンパイル時エラーが発生します。

    必須: ParameterizedType が見つかりました: CAP#1 が新しい型変数であるクラス: CAP#1 は ? のキャプチャからリストを拡張します リストを拡張します

この関連するSOの投稿を見たことがありますが、それは私を啓発していません。

4

1 に答える 1

4

ジェネリック クラスのすべてのインスタンスは、同じランタイム クラスを共有します。

new ArrayList<Integer>().getClass() == new ArrayList<String>().getClass()

別の言い方をすれば、ランタイムは、ジェネリック クラスのインスタンス化に使用される実際の型引数を追跡しません。ただし、ソース コードで宣言されている型は認識しており、それが getGenericSuperclass() とその仲間が返すものです。したがって、クラスがある場合:

class Environment extends HashMap<String, Object> {

}

表現

new Environment().getClass().getGenericSuperclass()

戻り値

java.util.HashMap<java.lang.String, java.lang.Object>

対照的に、あなたが宣言する場合

class Environment<E> extends HashMap<String, E> {
}

同じ式が返されます

java.util.HashMap<java.lang.String, E>

そうです、getGenericSuperclass は、ソース コードで宣言されている実際の型パラメーターを返しますが、これらの型パラメーターには、別の場所で宣言された型変数が含まれる場合があります。

また、スーパークラスをParameterizedTypeにキャストできるのに、クラス自体をキャストできない理由も明確ではありません。

ParametrizedTypeオブジェクトは型引数の空でないリストを持つコンパイル時の型を表し、オブジェクトClassは実行時型 (型引数を持たない) を表します。したがって、 aClassは a ではありませんParametrizedType

于 2013-06-02T20:15:52.473 に答える