`
adapterofcoms
  • 浏览: 72364 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

在运行时,你能修改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 

 

 

 

 

 

2
0
分享到:
评论
1 楼 fengzhizi715 2010-03-29  
哥 你太强了 呵呵

相关推荐

    Java运行于手机的一个联系人管理小程序.rar

    // 值为true时为增加记录,否则为修改记录  Ticker ticker = new Ticker("个人信息 "); //实例化Ticker对象  static final Command EXIT = new Command("退出",Command.STOP,1); //实例化命令  static final ...

    【05-面向对象(下)】

     –在定义该final变量时指定了初始值;  –该初始值可以在编译时就被确定下来。 final方法 •final方法 •final 修饰的方法不可以被重写。 •final 修饰的方法仅仅是不能重写,但它完全可以被重载...

    封装给java使用的 web报表 rm webrm 报表1.0.0.1版正式版

    任何个人或组织可以自由使用,可以任意修改、复制、发布,但要保留本人的声明以遵重本人的劳动成果,并且不能用于任何商业目的。 本人提供的是免费报表,不与商家争长短,但希望对你有用: 使用方法: 范例使用的是...

    封装给java使用的 web报表 rm webrm 报表1.0.0.1版,升级版

    任何个人或组织可以自由使用,可以任意修改、复制、发布,但要保留本人的声明以遵重本人的劳动成果,并且不能用于任何商业目的。 本人提供的是免费报表,不与商家争长短,但希望对你有用: 使用方法: 范例使用的是...

    封装给java使用的 web插件报表(修正版本)

    然后修改classes文件下的 db.properties 的连接。 然后把项目放在tomcat下运行既可: 起作用的关键文件:RMVIEWP.CAB 文件,客户端插件 Lib下的两个包:RMVIEW.jar,commons-logging.jar 使用接口: package ...

    封装给java使用的 web插件报表

    然后修改classes文件下的 db.properties 的连接。 然后把项目放在tomcat下运行既可: 起作用的关键文件:RMVIEWP.CAB 文件,客户端插件 Lib下的两个包:RMVIEW.jar,commons-logging.jar 使用接口: package ...

    封装给java使用的 web插件报表 (修正版本)

    然后修改classes文件下的 db.properties 的连接。 然后把项目放在tomcat下运行既可: 起作用的关键文件:RMVIEWP.CAB 文件,客户端插件 Lib下的两个包:RMVIEW.jar,commons-logging.jar 使用接口: package ...

    小日本视频转换器

    TMPGEnc 是日本人堀浩行开发的一套老牌的高画质视频编码转换工具软件,在 Canopus ProCoder v2.0 Final 推出以前,一直是视频转换领域的画质冠军,支持 VCD、SVCD、DVD 以及所有主流媒体格式 (Windows Media、Real ...

    经典SQL语句大全

    在SQLServer中分组时:不能以text,ntext,image类型的字段作为分组依据 在selecte统计函数中的字段,不能和普通的字段放在一起; 13、对数据库进行操作: 分离数据库: sp_detach_db; 附加数据库:sp_attach_db 后...

    数据库操作语句大全(sql)

    在SQLServer中分组时:不能以text,ntext,image类型的字段作为分组依据 在selecte统计函数中的字段,不能和普通的字段放在一起; 13、对数据库进行操作: 分离数据库: sp_detach_db; 附加数据库:sp_attach_db ...

    sql经典语句一部分

    在SQLServer中分组时:不能以text,ntext,image类型的字段作为分组依据 在selecte统计函数中的字段,不能和普通的字段放在一起; 13、对数据库进行操作: 分离数据库: sp_detach_db; 附加数据库:sp_attach_db 后...

    [原创]自己工作中常用的模板库,简化你的工作

    ★ 当把"智能指针/stl迭代器/C指针/前三者嵌套"都视为指针时,其内的最终值(非指针值)是一致的,在模板函数中,某些场景需要取得其最终的非指针值。 应用场景:转发模板函数,如 template<typename T> void ...

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part1

    实例148 计算程序运行时间 176 第3章 Web页面交互 178 3.1 获取表单元素的值 179 实例149 设计论坛登录界面 179 实例150 可以上传图片的表单 180 实例151 通过POST方法提交表单元素 182 实例152 通过$_POST方法获取...

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part2

    实例148 计算程序运行时间 176 第3章 Web页面交互 178 3.1 获取表单元素的值 179 实例149 设计论坛登录界面 179 实例150 可以上传图片的表单 180 实例151 通过POST方法提交表单元素 182 实例152 通过$_POST方法获取...

    javaSE代码实例

    1.4.2 编译运行 9 1.5 小结 11 第2章 基本数据类型——构建Java 大厦的基础 12 2.1 源代码注释 12 2.1.1 单行注释 12 2.1.2 区域注释 12 2.1.3 文档注释 13 2.2 基本数据类型 14 2.2.1 整型 15 ...

Global site tag (gtag.js) - Google Analytics