Method.invoke 可在运行时动态调用方法,需先通过Class.forName加载类、getDeclaredMethod定位方法(支持私有方法)、setAccessible(true)设访问权限,再以实例(或null)和匹配参数调用,支持配置化类名与方法名。

Method.invoke 可以在运行时动态调用方法,但前提是你得先拿到 Method 对象 —— 而获取它并不依赖“写死类名”,关键在于如何通过反射机制定位到目标类和方法。核心思路是:**用类名字符串加载类、用方法名和参数类型匹配方法、再用实例或 null(静态方法)调用**。
用 Class.forName 动态加载类
只要你知道类的全限定名(比如 "com.example.ServiceImpl"),就能绕过编译期绑定:
- 注意包路径必须完整准确,否则抛
ClassNotFoundException - 如果类在模块路径下(Java 9+),需确保模块已导出该包
- 示例:
Class> clazz = Class.forName("com.example.UserService");
用 getDeclaredMethod 定位目标方法
有了 Class 对象后,用方法名 + 参数类型数组精准查找(比 getMethod 更灵活,支持私有/非 public 方法):
- 参数类型必须和目标方法签名严格一致,如
String.class、int.class、MyDto[].class - 若参数类型不确定,可先用
getDeclaredMethods()遍历筛选,比如按参数个数或名称模糊匹配 - 调用前建议
setAccessible(true)(尤其对 private 方法)
准备参数并执行 invoke
invoke 第一个参数是调用对象(null 表示静态方法),后续是实际参数值:
- 基本类型参数要装箱(如传
int值,用Integer.valueOf(123)或自动装箱) - 参数数量、顺序、类型必须与
Method对象描述的一致,否则抛IllegalArgumentException - 捕获
InvocationTargetException—— 它包装了目标方法内部抛出的真实异常
实用小技巧:避免硬编码类名和方法名
把类名、方法名、参数类型等配置化,比如从 JSON、YAML 或数据库读取:
- JSON 示例:
{"className":"com.example.Calculator","methodName":"add","paramTypes":["int","int"],"args":[5,3]} - 解析后动态构建
Class[] paramTypes数组(可用ClassUtils.resolveClassName等工具辅助) - 对泛型或复杂类型,考虑用类型签名字符串(如
"java.util.List<java.lang.String>")配合 TypeResolver 解析

















