Java可通过反射修改私有变量:先用getDeclaredField获取字段,再调用setAccessible(true)绕过访问检查,最后用set()赋值;注意字段名大小写敏感、final字段修改不可靠、模块化环境下需--add-opens授权。

Java 中可以通过反射机制修改私有变量的值,核心步骤是:获取 Field 对象、调用 setAccessible(true) 跳过访问检查、再用 set() 方法赋新值。
获取目标字段对象
使用 Class.getDeclaredField(String name) 获取指定名称的私有字段。注意必须用 getDeclaredField(而非 getField),因为后者只返回 public 字段。
- 字段名必须完全匹配,包括大小写
- 若字段在父类中,需向上遍历父类的
getDeclaredField - 如果字段不存在,会抛出
NoSuchFieldException
关闭访问权限检查
调用 field.setAccessible(true) 临时绕过 Java 的访问控制。这是修改私有字段的关键一步,否则调用 set() 时会抛出 IllegalAccessException。
-
setAccessible(true)不会改变字段本身的修饰符,只是让反射操作跳过运行时检查 - 在安全管理器(SecurityManager)启用的环境中,该调用可能被拒绝
- JDK 9+ 模块系统下,还需通过
--add-opens参数开放模块包的反射权限
设置新值
调用 field.set(Object obj, Object value) 为指定对象的该字段赋值。第一个参数是目标实例(静态字段传 null),第二个参数是待设置的值。
立即学习“Java免费学习笔记(深入)”;
- 基本类型字段需传对应包装类或自动装箱值(如
int字段可传42或Integer.valueOf(42)) - 类型不匹配会抛出
IllegalArgumentException - 若字段是 final 且已初始化,JVM 可能仍允许修改,但后续行为不可靠(尤其 JDK 12+ 对 final 字段反射限制更严格)
完整示例代码
假设有一个类:class Person { private String name = "Alice"; }
修改其私有字段:
Person p = new Person();
Field nameField = Person.class.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(p, "Bob");
System.out.println(p.getName()); // 注意:若 getName() 是 public 方法且返回 name,此时输出为 "Bob"


















