温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

反射可以修改final吗

发布时间:2026-10-04 16:48:06 来源:亿速云 阅读:92 作者:小樊 栏目:编程语言

简短结论:普通 Java 反射本身不能直接修改 final 字段的值(会被 JVM 限制或优化挡住),但通过“先去掉 final 修饰符再改”的黑魔法,在多数情况下可以改成功,不过不保证、也不安全。

下面分情况说清楚。


1. 普通反射改 final 字段:不行

class A {
    private final int x = 10;
}
Field f = A.class.getDeclaredField("x");
f.setAccessible(true);
f.set(a, 20); // 通常抛 IllegalAccessException 或无效

原因:

  • final 字段在 JVM 语义上是“不可变”
  • 反射在设置 final 字段时会被限制

2. 常见“绕过 final”的方式(黑魔法)

方式一:先改 modifiers

Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);

f.set(a, 20);

✅ 在很多 JDK 8 及以前版本有效
❌ 在新 JDK(9+)中可能失效或被警告


3. 即使“改成功”,也不一定生效

这是最关键的一点。

情况一:基本类型 / String 常量

private final int x = 10;
private final String s = "abc";
  • 可能被 JIT 内联
  • 你改了字段,但代码用的还是旧值
System.out.println(a.x); // 可能还是 10

情况二:static final 常量

static final int C = 10;
  • 编译期常量
  • 直接被替换为字面量
  • 反射改了也没用

情况三:普通对象引用

private final List<String> list = new ArrayList<>();
  • 改 list 指向另一个对象:可能成功
  • 改 list 内部内容:本来就可以

4. 模块系统(Java 9+)限制

InaccessibleObjectException
  • java.base 等模块禁止非法反射
  • setAccessible(true) 可能直接失败

5. 结论总结

问题 答案
反射能直接改 final 吗 ❌ 不能
用黑魔法能改吗 ⚠️ 有时能
改了一定生效吗 ❌ 不一定
生产环境能用吗 ❌ 绝对不建议

如果你愿意,我可以:

  • 给你一个 可运行示例(JDK 8 / 17 对比)
  • 解释 为什么 JIT 会无视你的修改
  • 或告诉你 哪些场景“看似 final 其实能改”

你更想看哪一种?

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手