必须用getDeclaredMethod而非getMethod,因其专用于获取本类声明的所有成员(含private、static等),而getMethod只查public方法;setAccessible(true)仅对当前Method实例生效,须在invoke前调用且不可省略。

反射调用静态私有方法时,setAccessible(true) 必须作用于 getDeclaredMethod 获取到的 Method 实例上,且只对该实例生效——它不是全局开关,也不影响其他 Method 对象或后续同类调用。
为什么必须用 getDeclaredMethod 而非 getMethod
getMethod 只查找 public 方法(包括父类继承的),完全忽略 private 成员。静态私有方法只能通过 getDeclaredMethod 定位,因为它专用于获取本类声明的所有成员(含 private、static、final 等修饰的方法)。
- 错误写法:
clazz.getMethod("doSomething", String.class)→ 直接抛NoSuchMethodException - 正确写法:
clazz.getDeclaredMethod("doSomething", String.class)
setAccessible(true) 的调用时机和作用范围
该调用必须在 invoke() 之前执行,且仅解除当前 Method 实例的访问检查。即使对同一方法多次反射获取,每次得到的 Method 对象都需单独调用 setAccessible(true)。
将 WCAG 2 AA 无障碍标准应用于设计系统、UI 组件和网页——通过可运行的验证器进行对比度计算,采用设计 token 模式使颜色天生可访问,设定排版和焦点状态规则,并提供语义检查清单。适用于构建或审查 UI。
- 同一个类中多次调用同名私有静态方法?每次都要重新 getDeclaredMethod + setAccessible
- 两个不同 Method 对象指向同一签名的方法?各自 setAccessible 互不影响
- setAccessible 的状态不参与 equals/hashCode 比较,无法靠缓存 Method 对象省略这步
JDK 9+ 模块系统下的关键限制
即使 setAccessible(true) 已调用,若目标类所在模块未显式开放(opens),JVM 仍会抛 InaccessibleObjectException,尤其常见于 java.base 中的类。
- 典型报错:
java.lang.reflect.InaccessibleObjectException: Unable to make static method accessible - 临时解决:启动参数加
--add-opens java.base/java.lang=ALL-UNNAMED(按实际包和模块调整) - 长期建议:避免反射核心类库;如必须,优先查 JDK 是否已提供替代 API(如 String::isLatin1 替代直接读 coder 字段)
调用静态方法时的 invoke 参数处理
静态方法不依赖实例,invoke 的第一个参数可传 null,但不能省略。JVM 会明确要求接收一个 Object 类型实参,null 表示“无目标实例”。
- 正确:
method.invoke(null, "arg1", 42) - 错误:
method.invoke("arg1", 42)→ 报 IllegalArgumentException(参数个数不匹配) - 注意:参数类型必须严格匹配,
int.class和Integer.class视为不同签名










