class WithPrivateFinalField {
private final String s = "I’m totally safe";
public String toString() {
return "s = " + s;
}
}
WithPrivateFinalField pf = new WithPrivateFinalField();
System.out.println(pf);
Field f = pf.getClass().getDeclaredField("s");
f.setAccessible(true);
System.out.println("f.get(pf): " + f.get(pf));
f.set(pf, "No, you’re not!");
System.out.println(pf);
System.out.println(f.get(pf));
Output:
s = I’m totally safe
f.get(pf): I’m totally safe
s = I’m totally safe
No, you’re not!
为什么会这样,你能解释一下吗?第一个打印告诉我们私有“s”字段没有改变,正如我所期望的那样。但是,如果我们通过反射获取该字段,则第二个打印显示它已更新。
这个答案 https://stackoverflow.com/questions/3301635/change-private-static-final-field-using-java-reflection关于该主题的内容非常详尽。
JLS 17.5.3 最终字段的后续修改
即便如此,仍然存在许多并发症。如果最后一个字段是
在字段声明中初始化为编译时常量,
可能无法观察到最终字段的更改,因为该字段的使用
Final 字段在编译时被替换为编译时
持续的。
但是,如果您仔细阅读上面的段落,您可能会在这里找到一种方法(设置private final
构造函数中的字段而不是字段定义中的字段):
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
WithPrivateFinalField pf = new WithPrivateFinalField();
System.out.println(pf);
Field f = pf.getClass().getDeclaredField("s");
f.setAccessible(true);
System.out.println("f.get(pf): " + f.get(pf));
f.set(pf, "No, you’re not!");
System.out.println(pf);
System.out.println("f.get(pf): " + f.get(pf));
}
private static class WithPrivateFinalField {
private final String s;
public WithPrivateFinalField() {
this.s = "I’m totally safe";
}
public String toString() {
return "s = " + s;
}
}
}
然后输出如下:
s = I’m totally safe
f.get(pf): I’m totally safe
s = No, you’re not!
f.get(pf): No, you’re not!
希望这个对你有帮助。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)