【问题标题】:Java :: obtaining parameterized type names at runtimeJava :: 在运行时获取参数化类型名称
【发布时间】:2013-06-02 19:42:17
【问题描述】:

以下代码:

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 会产生以下编译时错误:

    必需:参数化类型 发现:类 其中 CAP#1 是一个新的类型变量: CAP#1 从捕获的 ? 扩展列表扩展列表

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

【问题讨论】:

标签: java generics reflection type-erasure


【解决方案1】:

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

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

【讨论】:

  • 最后一点,对我来说,为什么给定一个对象句柄,我可以得到它的超类的类型参数,但不能得到它的类的类型参数。
  • 因为类声明包含类型本身的parameters,但类型arguments 表示它的超类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-23
  • 2020-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多