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是类型参数名称?
  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 回答