反射允许你在运行时分析任意的对象。如果对象是泛型类的实例,关于泛型类型参数则得不到太多信息,因为它们会被擦除。

泛型Class类

Class 类是泛型的。例如,String.class 实际上是一个 Class 类的对象(事实上,是唯一的对象)。
类型参数十分有用,这是因为它允许 Class 方法的返回类型更加具有针对性。下面 Class 中的方法就使用了类型参数:

  1. T newInstance();
  2. T cast(Object obj);
  3. T[] getEnumConstants();
  4. Class<? super T> getSuperclass();
  5. Constructor<T> getConstructor(Class...paramentTypes);
  6. Constructor<T> getDecalredConstructor(Class...paramentTypes);

newInstance 方法返回一个实例,这个实例所属的类由默认的构造器获得。它的返回类型目前被声明为T,其类型与 Class 描述的类相同,这样就免除了类型转换。
如果给定的类型确实是 T 的一个子类型,cast 方法就会返回一个现在声明为类型 T 的对象,否则,抛出一个 BadCastException 异常。
Class 的 getSuperclass() 方法返回的 Class 类型是 Class<? super T>:

  1. Class<? super String> sup = String.class.getSuperclass();

如果这个类不是 enum 类或类型 T 的枚举值的数组,getEnumConstants 方法将返回 null。
最后,getConstructor 与 getdeclaredConstructor 方法返回一个 Constructor 对象。Constructor 类也已经变成泛型,以便 newInstance 方法有一个正确的返回类型。

虚拟机中的泛型类型信息

Java 泛型的卓越特性之一是在虚拟机中泛型类型的擦除。令人感到奇怪的是,擦除的类仍然保留一些泛型祖先的微弱记忆。例如,原始的Pair类知道源于泛型类 Pair,即使一个 Pair 类型的对象无法区分是由 Pair 构造的还是由 Pair 构造的。
可以使用反射 API 来确定:

  • 这个泛型方法有一个叫做 T 的类型参数。
  • 这个类型参数有一个子类型限定,其自身又是一个泛型类型。
  • 这个限定类型有一个通配符参数。
  • 这个通配符参数有一个超类型限定。
  • 这个泛型方法有一个泛型数组参数。

为了表达泛型类型声明,使用 java.lang.reflect 包中提供的接口 Type。
chapter_VIII-reflect_Type