the journey is the reward...

常用链接

统计

最新评论

在运行时,你能修改final field的值吗?

 

以[final int x=911] , [static final int x=912]为例,jdk1.6.0_16(为何如此版本详细,是因为下面还有个jdk的bug).

样例类:

class Test { 
 private final  int x=911;//modifiers:final->18,non-final->2
 static final private  int y=912;//modifiers:final->26,non-final->10 
 public int getX(){
  return x;
 }  
 public static int getY(){
  return y;
 } 

 Java中的final field意指常量,赋值一次,不可改变.编译器会对final field进行如下的优化:

e.g:

Test t=new Test();

凡是在程序中对t.x的引用,编译器都将以字面值911替换,getX()中的return x也会被替换成return 911;

所以就算在运行时你改变了x的值也无济于事,编译器对它们进行的是静态编译.

但是Test.class.getDeclaredField("x").getInt(t)除外;

 

那么如何在运行时改变final field x的值呢?

private final  int x=911;Field.modifiers为18,而private int x=911;Field.modifiers为2.

所以如果我们修改Field[Test.class.getDeclaredField("x")].modifiers由18[final]变为2[non-final],那么你就可以修改x的值了.

 Test tObj=new Test();  
 Field f_x=Test.class.getDeclaredField("x");  
  
  //修改modifiers 18->2
  Field f_f_x=f_x.getClass().getDeclaredField("modifiers");
  f_f_x.setAccessible(true);  
  f_f_x.setInt(f_x, 2/*non-final*/);
  
  f_x.setAccessible(true);
  f_x.setInt(tObj, 110);//改变x的值为110.  
  System.out.println("静态编译的x值:"+tObj.getX()+".------.运行时改变了的值110:"+f_x.getInt(tObj));
   
  f_x.setInt(tObj, 111);//你可以继续改变x的值为.  
  System.out.println(f_x.getInt(tObj));

但是想恢复原来的modifiers,f_f_x.setInt(f_x, 18/*final*/);这是无效的,因为Field只会初始化它的FieldAccessor引用一次.

 

在上面的过程中,我还发现了个jdk bug,你如果将上面的红色代码改为如下的代码:

f_f_x.setInt(f_x, 10/*这个数值是static non-final modifiers,而x是non-static的,这样就会使f_x得到一个static FieldAccessor*/);那么会引发A fatal error has been detected by the Java Runtime Environment.并产生相应的err log文件.显然JVM没有对这种情况加以处理.我已提交to sun bug report site. 

sun 于2010-3-26通知我,他们已承认该bug,bug id : 6938467.发布到外网可能有一到两天的延迟.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6938467 

 

 

 

posted on 2010-03-18 09:36 adapterofcoms 阅读(676) 评论(2)  编辑  收藏 所属分类: java techs

评论

# re: 在运行时,你能修改final field的值吗? 2011-01-06 10:02 我们

有的bug只是新功能的,其实不是bug  回复  更多评论   

# re: 在运行时,你能修改final field的值吗? 2011-01-06 10:03 我们

真正的bug是自身矛盾  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: