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



以下代码:

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 ?扩展列表

我看过这个相关的SO帖子,但它并没有给我启发。

一个泛型类的所有实例共享同一个运行时类:

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

最新更新