通过反射更改私人最终字段 [英] Changing private final fields via reflection

查看:127
本文介绍了通过反射更改私人最终字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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));

输出:

s = I’m totally safe
f.get(pf): I’m totally safe
s = I’m totally safe
No, you’re not!

为什么它以这种方式运作,你能解释一下吗?第一个印刷品告诉我们私人s字段没有像我预期的那样被改变。但是如果我们通过反射获得该字段,则第二个打印显示,它会更新。

Why does it work by this way, can you please explain? The first print tells us that the private "s" field has not been changed, as I expect. But if we get the field via reflection, the second print shows, it is updated.

推荐答案

这个答案不仅仅是详尽无遗的主题。

This answer is more than exhaustive on the topic.

JLS 17.5.3最终字段的后续修改

JLS 17.5.3 Subsequent Modification of Final Fields


即使这样,也会出现许多复杂情况。如果最终字段是
在字段声明中初始化为编译时常量,则可能无法观察到
对最终字段的更改,因为在编译时替换了
final字段的使用编译时
常量。

Even then, there are a number of complications. If a final field is initialized to a compile-time constant in the field declaration, changes to the final field may not be observed, since uses of that final field are replaced at compile time with the compile-time constant.

但是,如果你仔细阅读上面的段落,你可能会找到一种方法在这里(在构造函数中而不是在字段定义中设置私有最终字段):

But, if you read the paragraph above very carefully, you may find a way around here (set the private final field in the constructor instead of in the field definition):

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 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!

希望这会有所帮助。

这篇关于通过反射更改私人最终字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆