它是 Java 反射 API 中的一个核心接口,用于表明泛型类型变量,例如在泛型类、泛型方法中声明的 <T>、<E>、<K, V> 中的 T、E、K、V 等。
一、官方定义
public interface TypeVariable<D extends GenericDeclaration> extends Type {
Type[] getBounds(); // 获取上界(如 T extends Number → [Number.class])
D getGenericDeclaration(); // 获取声明此类型变量的“泛型声明”(类/方法/构造器)
String getName(); // 获取变量名,如 "T", "E"
}
二、核心概念解析
1. 什么是 TypeVariable?
- 它代表的是你在代码中写的 <T>、<E> 这种类型参数(Type Parameter)。
- 它不是具体类型,而是一个“占位符”,在编译时被擦除,在运行时通过反射可获取其元信息。
- 它只能出目前泛型定义中:
- 泛型类:class Box<T> { … }
- 泛型方法:public <T> T get() { … }
- 泛型构造器:public <T> MyClass(T t) { … }
2. 三个核心方法详解
String getName()
返回类型变量的名字:
class Pair<K, V> { ... }
TypeVariable<?>[] tvs = Pair.class.getTypeParameters();
System.out.println(tvs[0].getName()); // K
System.out.println(tvs[1].getName()); // V
Type[] getBounds()
返回类型变量的上界(支持多重边界):
class Box<T extends Number & Comparable<T>> { ... }
TypeVariable<?> tv = Box.class.getTypeParameters()[0];
Type[] bounds = tv.getBounds();
// bounds[0] → Number (Class)
// bounds[1] → Comparable<T> (ParameterizedType)
⚠️ 注意:
- 如果没有显式写 extends,默认上界是 Object。
- 边界可能是 Class、ParameterizedType、甚至另一个 TypeVariable。
D getGenericDeclaration()
返回声明这个类型变量的“泛型声明体”:
- 如果是类泛型 → 返回 Class<?>
- 如果是方法泛型 → 返回 Method
- 如果是构造器泛型 → 返回 Constructor<?>
public class Test {
public <T extends String> void method(T t) { }
}
Method method = Test.class.getMethod("method", String.class);
TypeVariable<Method> tv = method.getTypeParameters()[0];
Method declaringMethod = tv.getGenericDeclaration(); // 就是 method 本身
三、TypeVariable 出现场景
场景 1:从泛型类获取
class Container<T extends Number> { }
TypeVariable<?>[] tvs = Container.class.getTypeParameters();
for (TypeVariable<?> tv : tvs) {
System.out.println(tv.getName() + " extends " + Arrays.toString(tv.getBounds()));
}
// 输出: T extends [class java.lang.Number]
场景 2:从泛型方法获取
public <E extends Exception> void handle(E e) throws E { }
Method method = ...;
TypeVariable<Method> tv = method.getTypeParameters()[0];
System.out.println(tv.getName()); // E
System.out.println(Arrays.toString(tv.getBounds())); // [class java.lang.Exception]
四、重大注意事项
1. TypeVariable ≠ 具体类型
你不能通过 TypeVariable 获取 Class<T>,由于:
- T 可能是 ? extends Number,没有具体类;
- T 可能是另一个 TypeVariable;
- T 可能是 ParameterizedType(如 Comparable<T>);
✅ 正确做法:递归解析边界,或结合子类实际类型推断(如 Spring、MyBatis 所做)。
2. 类型擦除不影响反射元数据
虽然 JVM 运行时擦除泛型,但 .class 文件中保留了 Signature 属性,可通过反射读取:
// 即使运行时是 Object,反射仍能拿到 T 的定义
Field field = ...;
Type type = field.getGenericType(); // 可能是 TypeVariable
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...


