java反射可通过setaccessible(true)绕过访问控制修改私有字段,需用getdeclaredfield获取字段,注意大小写匹配、父子类字段查找限制及jdk9+模块化权限配置。

Java 反射可以获取并修改私有成员变量,但需绕过访问控制检查,核心是调用 setAccessible(true)。
获取私有字段对象
使用 Class.getDeclaredField(String name) 获取字段(注意不是 getField(),后者只返回 public 字段)。
- 字段名必须完全匹配,包括大小写
- 若字段不存在,会抛出
NoSuchFieldException - 父类的私有字段无法通过子类的
getDeclaredField直接获取,需在父类 Class 中查找
绕过访问权限检查
调用字段对象的 setAccessible(true) 方法,临时取消 Java 的访问控制检查。
- 该操作仅影响当前 Field 实例,不改变类定义
- JDK 9+ 在模块化环境下可能受
SecurityManager或模块导出限制,需确保模块已开放反射权限(如--add-opens java.base/java.lang=ALL-UNNAMED) - 部分安全敏感环境(如 Android、某些容器)可能禁止此操作
读取和修改私有字段值
通过 get(Object obj) 和 set(Object obj, Object value) 操作字段值。
-
get(null)仅适用于 static 字段;实例字段必须传入对应对象实例 - 基本类型字段(如
int)建议用getInt()/setInt()等专用方法,避免自动装箱/拆箱异常 - 修改 final 字段需额外处理:JVM 允许反射修改,但编译器可能内联 final 值,导致运行时行为不一致(不推荐修改 final 字段)
完整示例代码
假设有一个类:
class Person {private String name = "Alice";
private final int age = 30;
}
反射修改 name 字段:
Person p = new Person();Field nameField = Person.class.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(p, "Bob");
System.out.println(nameField.get(p)); // 输出 "Bob"
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











