日期:2014-05-20  浏览次数:20878 次

通过反射修改final实例变量,求一合理解释

public class Test {
private final String value = "木有修改";

public static void main(String[] args) throws Exception {
Test t = new Test();
Field field = t.getClass().getDeclaredField("value");
field.setAccessible(true);
field.set(t, "修改了");

System.out.println(field.get(t)); //此处打印  修改了

System.out.println(t.value); //但直接调用却打印   木有修改

//怀疑是Field缓存了?重建个Field
Field field2 = t.getClass().getDeclaredField("value");
System.out.println(field2.get(t));//此处还是打印  修改了
}
}


这是怎么造成的?
------最佳解决方案--------------------

field.setAccessible(true);
field.set(t, "update");
如果底层字段为 final 字段,则该方法将抛出一个 IllegalAccessException,除非 setAccessible(true) 已经继承该字段并且该字段是一个非静态字段。在通过程序的其他部分可以访问类的实例之前,只有使用空白 final 字段反序列化或重构类的实例期间,以这种方式设置 final 字段才有意义。在其他任何上下文中使用该方法都可能会有不可预知的结果,包括程序的其他部分继续使用该字段的原始值的情况。

------其他解决方案--------------------
引用:
CSS code?



1234

field.setAccessible(true);         field.set(t, "update"); 如果底层字段为 final 字段,则该方法将抛出一个 IllegalAccessException,除非 setAccessible(true) 已经继承该字段并且该字段是一个非静态字段。在通过程序的其他部分可以访问类的实例之前,只……


OK,谢了,知道这是在什么时候可以使用了

public class Test {
private final String value;

public Test() throws Exception {
value = "123"; //先赋值 “123”
Field field = this.getClass().getDeclaredField("value");
field.setAccessible(true);
field.set(this, "abc"); //更改为  “abc”
}

public static void main(String[] args) throws Exception {
Test t = new Test();
System.out.println(t.value);//打印   abc
}
}