Java反射无法动态执行带泛型参数的方法,因泛型被擦除;但可调用声明泛型的方法,需按擦除后类型获取Method、传具体实参,返回值需强转,并可用getGenericParameterTypes()获取源码泛型信息。

Java 反射无法真正“动态执行带有泛型参数的方法”——因为泛型在编译后被擦除(type erasure),运行时方法签名中不保留泛型类型信息。但你可以通过反射调用**声明了泛型参数的方法**,只要传入的实参类型在运行时是具体、可识别的(如 String、List<integer></integer> 等),JVM 就能完成类型检查和调用。
1. 反射调用泛型方法本身不需要特殊处理
泛型方法(如 <t> T getValue(T input)</t>)在字节码中就是普通方法,只是多了 Signature 属性记录泛型信息。反射调用时,你只需按常规方式获取 Method 并 invoke:
- 用
getDeclaredMethod("methodName", parameterTypes...)获取方法,参数类型写**运行时实际类型**(如String.class,不是List<string>.class</string>—— 后者语法错误) - 调用
method.invoke(obj, args...)时,传入的具体对象类型必须与方法签名兼容(JVM 会做桥接方法或类型检查) - 返回值是
Object,需手动强转(泛型擦除后无法自动推导)
2. 处理形参为泛型集合(如 List)的关键点
方法声明可能是:void process(List<string> list)</string>。运行时该参数类型被擦除为 List.class,所以反射查找时应使用:
-
getMethod("process", List.class)—— ✅ 正确:匹配擦除后的类型 -
getMethod("process", List<string>.class)</string>—— ❌ 编译不过:泛型类字面量非法
调用时传入的实参也只需是 List 的具体实现(如 new ArrayList()),JVM 不校验泛型实参,只校验是否为 List 子类型。
立即学习“Java免费学习笔记(深入)”;
3. 获取泛型参数的真实类型(用于日志、校验或序列化)
如果需要知道某个方法参数在源码中声明的泛型(例如 List<user></user>),得解析 Method.getGenericParameterTypes():
- 它返回
Type[],对泛型参数可能为ParameterizedType - 可从中提取原始类型(
getRawType())和实际类型参数(getActualTypeArguments()) - 注意:这仅用于元数据读取,不影响 invoke 行为
void f(List<integer> x)</integer> 中 List<integer></integer> 的泛型参数ParameterizedType pType = (ParameterizedType) method.getGenericParameterTypes()[0];<br> Class<?> raw = (Class<?>) pType.getRawType(); // List.class<br> Type arg = pType.getActualTypeArguments()[0]; // Integer.class
4. 注意桥接方法(Bridge Methods)干扰
当泛型类继承/实现含泛型方法的父类或接口时,编译器可能生成桥接方法(如 Object get())。直接 getMethods() 可能拿到多个同名方法。建议:
- 优先用
getDeclaredMethod()明确指定参数类型,避免桥接方法干扰 - 必要时过滤掉
isBridge() == true的方法


















