反射调用方法必须先获取Class对象,可通过类名字符串(Class.forName)、实例(obj.getClass)或接口/父类(Spring/ServiceLoader)等运行时途径获取;调用前需验证方法访问权限、参数类型并捕获相应异常。

不能在完全不知道类名的情况下用 Method.invoke 触发方法——因为反射必须先获取 Class 对象,而获取 Class 就需要知道类名(或通过实例、ClassLoader、上下文等间接途径)。但“不知道类名”常指编译期未知、运行时才确定,这正是反射的典型使用场景。关键在于:**如何在运行时安全、可靠地拿到目标类和方法**。
通过类名字符串加载 Class
这是最常见方式。只要你知道类的全限定名(如 "com.example.ServiceImpl"),就能用 Class.forName() 获取 Class 对象:
- 确保类在当前 ClassLoader 可见(避免
ClassNotFoundException) - 类名必须完整,包括包路径;若用简写名(如
"ServiceImpl"),需自行拼接或维护映射表 - 建议加 try-catch,并考虑缓存
Class实例提升性能
通过已有对象反推 Class
如果你有目标对象的实例(哪怕类型是 Object),可直接调用 obj.getClass():
- 适用于回调、插件、SPI 等场景,比如框架传入一个实现类实例
- 注意区分
getClass()和getDeclaredClass()(后者不存在,别混淆) - 拿到
Class后,再用getMethod()或getDeclaredMethod()查找方法
通过接口或父类缩小查找范围
如果只知道接口名(如 UserService)或基类,可通过 Spring、ServiceLoader 或自定义扫描找到具体实现类:
- Spring 中可用
ApplicationContext.getBeansOfType(UserService.class)获取所有实现 - Java SPI 可通过
ServiceLoader.load(UserService.class)加载实现 - 结合注解(如
@Handler("pay"))+ 类路径扫描,实现“按标识找类”
安全调用方法的必要检查
拿到 Method 后,invoke 前务必验证:
- 检查方法是否为
public(或设setAccessible(true)访问私有方法) - 核对参数类型是否匹配,避免
IllegalArgumentException - 捕获
IllegalAccessException、InvocationTargetException等异常,后者包装了目标方法内部抛出的异常 - 静态方法调用时,
invoke的第一个参数传null
不复杂但容易忽略。核心不是“绕过类名”,而是构建一条从已知线索(字符串、实例、接口、配置)到可执行方法的可靠路径。

















