Java 17中如何通过反射修改非静态final字段?
在Java 17中通过反射修改非静态final字段的方法
你之前的代码在Java 17中报错,是因为从Java 12开始,Field类内部的modifiers字段被移除了,直接通过反射获取该字段会抛出NoSuchFieldException。针对非静态final字段,其实不需要修改modifiers,直接调用Field.set()方法就能完成修改,前提是绕过相关限制。
可行代码示例
import java.lang.reflect.Field; class Foo { private final String bar; public Foo(String bar) { this.bar = bar; } public String getBar() { return this.bar; } } public class Example { public static void main(String[] args) throws Exception { Foo foo = new Foo("foobar"); System.out.println("修改前: " + foo.getBar()); Field field = Foo.class.getDeclaredField("bar"); // 解除字段的访问限制 field.setAccessible(true); // 直接修改字段值,无需操作modifiers field.set(foo, "new modified value"); System.out.println("修改后: " + foo.getBar()); } }
关键注意事项
- 仅适用于非静态final字段:静态final字段在JVM初始化后会被JIT编译器缓存,几乎无法通过反射修改,这一点和你了解的一致。
- 模块系统限制:如果你的代码是模块化项目(使用
module-info.java),需要确保目标包被开放给java.base模块,或者启动时添加参数:java --add-opens 你的模块名/你的包名=java.base Example,否则会抛出IllegalAccessException。 - JIT优化问题:如果JIT已经将final字段的值内联到调用代码中,修改后可能看不到预期效果。可以通过添加
-Xint参数禁用JIT编译,或者确保代码逻辑不会触发内联优化。 - 生产环境谨慎使用:这种操作打破了Java的封装设计和不可变性约定,可能导致不可预期的bug,仅建议用于调试、测试等特殊场景。
内容的提问来源于stack exchange,提问作者godfather
相关产品推荐
相关产品推荐

