Java ::在运行时获取参数化类型名称

时间:2013-06-02 19:42:17

标签: java generics reflection type-erasure

以下代码:

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 是类型参数名称?
  2. 我觉得奇怪的是我不得不特意解释名字“E”(我想是“S”,“U”等等,如果存在的话)。如果我有一个“E”级怎么办?此外,方法名称为get_ Actual _TypeArguments。鉴于类型参数像变量一样充当占位符,我发现一个方法应该返回变量的名称是非常奇怪的。我在这里错过了什么吗?
  3. 另外,我不清楚为什么我可以将超类强制转换为 ParameterizedType 而不是类本身。尝试将 li.getClass()的结果转换为 ParameterizedType 会产生以下编译时错误:

    必需:ParameterizedType 发现:上课           其中CAP#1是一个新的类型变量:              CAP#1扩展了List的捕获?扩展名单

  4. 我见过这个relevant SO post,但它没有启发我。

1 个答案:

答案 0 :(得分: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对象是运行时类型(它没有任何类型参数)。因此,Class不是ParametrizedType

相关问题