Java反射可通过getDeclaredFields()递归获取含父类的私有字段,调用setAccessible(true)绕过访问检查后用Field.set()赋值,但final字段在JDK12+默认不可修改,生产环境不推荐强行修改。

Java反射可以获取并修改私有字段,但需绕过访问控制检查,操作时要注意安全性和适用场景。
获取所有私有字段(包括父类)
使用 getDeclaredFields() 获取本类声明的所有字段(含 private),再递归遍历父类;getFields() 只返回 public 字段,不适用。
- 调用
clazz.getDeclaredFields()得到本类全部字段数组 - 通过
clazz.getSuperclass()向上追溯,对每个父类重复调用getDeclaredFields() - 注意:Object 类的字段(如
serialVersionUID)通常无需处理,可设终止条件(如superclass == null)
设置私有字段可访问(关键步骤)
默认 private 字段不可直接读写,必须调用 setAccessible(true) 禁用 Java 访问检查。
- 对每个
Field对象执行field.setAccessible(true) - 该操作仅影响当前
Field实例,不影响 JVM 全局策略 - JDK 9+ 在模块化环境下可能受
--illegal-access策略限制,建议开发期明确添加 JVM 参数(如--add-opens java.base/java.lang=ALL-UNNAMED)
对私有字段赋值(支持基本类型与对象)
使用 Field.set(Object obj, Object value) 赋值;基本类型自动装箱,但注意类型匹配。
立即学习“Java免费学习笔记(深入)”;
- 若字段是
int,传入Integer或int均可(反射自动处理) - 若字段是
final,JDK 12+ 默认禁止修改(会抛IllegalAccessException),需额外绕过:先用Field.modifiers修改修饰符(需 Unsafe 或反射修改 Modifier 的 static final 字段,**生产环境不推荐**) - 示例:
field.set(instance, "new value");—— instance 为待修改的对象实例
完整工具方法示例
以下是一个安全、可复用的工具方法片段(不含 final 处理):
public static void setPrivateField(Object target, String fieldName, Object value) throws Exception {
Class<?> clazz = target.getClass();
Field field = null;
while (clazz != null && field == null) {
try {
field = clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
if (field == null) throw new NoSuchFieldException("Field " + fieldName + " not found");
field.setAccessible(true);
field.set(target, value);
}


















