Method.invoke 可在运行时调用任意对象的任意方法,需依次完成:1. 用 Class.forName() 加载全限定名类;2. 用 getDeclaredMethod() 获取 Method 对象;3. 创建实例或设 setAccessible(true);4. 调用 invoke() 并处理三类异常。

Method.invoke 可以在运行时调用任意对象的任意方法,但前提是必须先获取到对应的 Method 对象。所谓“不知道具体类名”,实际是指在编译期无法确定目标类,需在运行时通过字符串、配置或用户输入等方式动态加载类并查找方法——这完全可行,关键在于补全反射所需的完整链条。
1. 从类名字符串加载 Class 对象
类名只是字符串,需要用 Class.forName() 将其转为可操作的 Class 类型:
- 确保类名是**全限定名**(如
"com.example.ServiceImpl"),不是简单类名 - 类必须在类路径中,否则抛
ClassNotFoundException - 如果类有静态初始化块或依赖未就绪,可能触发
ExceptionInInitializerError
示例:
Class> clazz = Class.forName("com.example.UserManager");2. 获取目标 Method 对象
有了 Class,再通过方法名和参数类型定位 Method:
- 用
getDeclaredMethod(name, ...paramTypes)获取私有/公有方法;用getMethod(...)仅获取 public 且可被继承的方法 - 参数类型必须精确匹配,比如
int.class和Integer.class不等价;基本类型和包装类要区分清楚 - 若方法重载,必须传入正确的参数类型数组,否则抛
NoSuchMethodException
示例(调用 public void process(String, int)):
Method method = clazz.getDeclaredMethod("process", String.class, int.class);3. 创建实例或获取静态方法调用权限
反射调用分两种场景:
-
实例方法:需先创建对象,如
clazz.getDeclaredConstructor().newInstance();若构造器私有,需先setAccessible(true) -
静态方法:直接调用
method.invoke(null, args...),第一个参数传null即可 - 若目标方法是 private 或包私有,调用前务必
method.setAccessible(true),否则抛IllegalAccessException
4. 安全执行 invoke 并处理异常
invoke() 是受检操作,需捕获三类核心异常:
-
IllegalAccessException:访问权限不足 → 补setAccessible(true) -
IllegalArgumentException:参数数量/类型不匹配 → 核对传参是否与getDeclaredMethod中声明一致 -
InvocationTargetException:目标方法内部抛出异常 → 其getCause()才是原始异常
建议统一 try-catch 并做日志或封装,避免异常穿透影响主流程。

















