`
adapterofcoms
  • 浏览: 74679 次
  • 性别: 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反射如何有效的修改final属性值详解

    然而,有时在特定场景下,我们可能需要在运行时修改`final`变量的值,比如在测试中模拟不同状态。本文将探讨如何通过Java反射有效地修改`final`属性值,并理解其中的限制。 首先,我们来看一个简单的例子,定义一个...

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

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

    java概述课件24反射.ppt

    这些功能使得Java程序具有很高的灵活性,能够在运行时检查类的结构,创建对象,调用方法,修改字段值等,广泛应用于插件系统、动态代理、序列化、框架开发等多个领域。 总的来说,Java反射提供了强大的能力,让...

    Hibernate配置文件加载后修改配置信息

    通过这种方式,我们可以在程序运行时动态修改配置文件中的信息,提高了系统的灵活性和安全性。 #### 四、总结 本文介绍了如何利用反射机制来修改Hibernate配置文件中的数据库连接信息,并通过自定义`...

    Java反射机制及各成份所对应的Reflection APIs

    此外,反射还能在运行时创建对象、设置字段值和调用方法,即使这些信息在编译时是未知的。 `java.lang.Class`是反射机制的核心,它代表了Java程序运行时的类和接口。每个Java类在加载到JVM时都会有一个对应的Class...

    auto_selling_machine final.zip

    FPGA是一种可编程的逻辑器件,它的主要特点是能够在硬件层面进行逻辑功能的配置和修改。与传统的ASIC(Application-Specific Integrated Circuit)相比,FPGA具有灵活性高、开发周期短、可重复利用等优点。在本项目...

    java反射机制 读者基础:具备Java 语言基础

    这种机制允许程序在运行时动态加载未知名称的类,进行字段的修改和方法的调用,从而增强了代码的灵活性和可扩展性。 Java反射API主要包含在`java.lang.reflect`包中,包括`Class`、`Method`、`Field`和`Constructor...

    Java面试题以及答案

    - `final`类中的成员变量如果是`final`的,则其值一旦被初始化就不能被修改。 #### 11. 继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么? 这类题目主要考查对象初始化顺序,包括静态变量、静态初始化...

    Integer缓存池案例1

    这段代码尝试获取并修改Integer的`value`字段,但在实际运行时会抛出异常,因为Integer不允许外部直接修改其内部状态。 总结一下,本案例涉及的知识点包括: 1. Integer对象的缓存池机制。 2. Java对象访问的句柄与...

    JAVA面试题解惑系列114页.pdf

    当你运行这段代码并创建一个`InitialOrderTest`的对象时,你会看到输出按照预期的顺序进行: 1. 静态变量 2. 静态初始化块 3. 变量 4. 初始化块 5. 构造器 在继承的情况下,这个顺序仍然适用,但有一些额外的考虑...

    Tomcat中一种半通用回显方法 - 先知社区1

    Java的反射API允许程序在运行时检查和修改类、接口、字段和方法的属性。在本例中,通过`Class.getDeclaredField()`获取私有常量`WRAP_SAME_OBJECT`的Field对象,然后使用`Field.setAccessible(true)`使其可访问,...

    JAVA 反射机制应用

    在Java中,反射机制的核心类是java.lang.Class,它代表了运行时的类信息。通过Class对象,我们可以动态地获取类的信息(如类名、方法、构造器等)并进行操作,这为程序提供了高度的灵活性和动态性。 1. **反射的...

    Java企业级开发综合技能知识总结

    - 反射机制允许程序在运行时检查和修改自身结构和行为的能力。 - 主要通过`Class`类及其相关API实现。 22. **类的反射机制中的包及核心类?** - 核心包:`java.lang.reflect`。 - 核心类:`Class`, `Constructor...

    Java反射大全

    反射机制使得Java程序在运行时能够获取关于自身的信息,如类、接口、字段和方法等,并能在运行时动态地创建对象、调用方法、修改属性。这使得Java具备了一定的动态性,虽然在传统的分类中它被归为静态类型语言。 1....

    反射和动态代理

    **反射** 是Java提供的一种机制,允许程序在运行时检查类、接口、字段和方法的信息,甚至能够动态调用方法和修改对象的状态。通过`java.lang.Class`类和`java.lang.reflect`包中的相关API,我们可以获取到类的结构...

    java程序员经典笔试面试题汇总

    答案是不会改变,因为即使去掉了 `final`,`a` 仍然是一个静态变量,它的初始化依然会在类加载时发生,因此顺序仍然是 `sss *** ###`。 #### 二、类的初始化顺序与继承关系 **题目背景**:本题目考察在Java中类...

    java面试题(尚学堂内部培训资源,绝对值得一看)

    - `final`变量一旦赋值就不能更改。 #### 11. 继承时候类的执行顺序问题 在Java中,当创建子类的实例时,会首先调用父类的构造方法,然后才是子类自身的构造方法。 #### 12. 内部类的实现方式 内部类可以通过...

    java经典面试

    - **反射**:在运行时检查和修改类、字段、方法等的能力。 - 主要涉及`Class`类、`Field`、`Method`、`Constructor`等。 #### 20. 类的返射机制中的包及核心类 - 包:`java.lang.reflect` - 核心类:`Class`、`...

Global site tag (gtag.js) - Google Analytics