注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

让一切都逝去吧

排骨炖泥菜/猪肝炒苹果/鱼籽狗肉汤/狗头薏米汤

 
 
 

日志

 
 

java修改static final常量值  

2014-11-11 11:27:15|  分类: Java |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
      java中,final标识的变量是不可修改的,但是通过反射的方式达到修改的目的。修改的示例也很简单,在这里http://stackoverflow.com/questions/2474017/using-reflection-to-change-static-final-file-separatorchar-for-unit-testing
public class EverythingIsTrue {
    static void setFinalStatic(Field field, Object newValue) throws Exception {
        field.setAccessible(true);

        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

        field.set(null, newValue);
    }
    public static void main(String args[]) throws Exception {
        setFinalStatic(Boolean.class.getField("FALSE"), true);

        System.out.format("Everything is %s", false); // "Everything is true"
    }
}

    关键点在于.setAccessible(true),并且修改modifiers去除final属性。获得修饰符的方式可以通过java.lang.reflect.Modifier,详细说明在这里
http://blog.csdn.net/xiao__gui/article/details/8141216
通过Modifier的isPublic、isPrivate、isStatic等方法,可以判断是否包含某些修饰符
boolean isStatic = Modifier.isStatic(field.getModifiers());
if(isStatic) {
    System.out.println(field.get(null).toString());
}
这里的field是静态类型的,因此field.get(null)方法的参数,可以是null,也可以是A.class这样的目标类,不用提供实例对象。查看java.lang.reflect.Modifier的代码,可以知道对修饰符的定义是通过二进制位来实现的。上面文章中有举例

public static,对应的整数就是二进制的:1001,也就是9。如下:

……

native

transient

volatile

synchronized

final

static

protected

private

public

 

0

0

0

0

0

1

0

0

1


源码中的完整定义如下
public static final int PUBLIC           = 0x00000001;
public static final int PRIVATE          = 0x00000002;
public static final int PROTECTED        = 0x00000004;
public static final int STATIC           = 0x00000008;
public static final int FINAL            = 0x00000010;
public static final int SYNCHRONIZED     = 0x00000020;
public static final int VOLATILE         = 0x00000040;
public static final int TRANSIENT        = 0x00000080;
public static final int NATIVE           = 0x00000100;
public static final int INTERFACE        = 0x00000200;
public static final int ABSTRACT         = 0x00000400;
public static final int STRICT           = 0x00000800;

根据数值,得到完整的顺序是这样的
strict,abstract,interface,native,transient,volatile,synchronized,final,static,protected,private,public
      由此就可以了解field.getModifiers() & ~Modifier.FINAL这部分的含义的,先~Modifier.FINAL将final所在的位设置为0,其他所有位设置为1。field.getModifiers() & ~Modifier.FINAL与的操作,就是将field的modifiers属性修饰符中final给去除掉。

      但是在自己尝试的过程中,发现一个问题。设置final变量的方法是field.set(),如果在这个方法之前调用了field.get()方法,顺序如下面这样
field.get(null).toString();
...
field.set(null, newValue);
这时对final变量的赋值就会报错,就算.setAccessible(true);也是没有用的。具体原因尚不清楚,估计需要跟踪源码才能查清楚。

      需要注意的是,对于int、long、boolean以及String等基本类型,由于编译器优化的原因,很多使用常量的地方的值还是原来的数值。如
if (index > maxFormatRecordsIndex) {
    index  =  maxFormatRecordsIndex;
}
maxFormatRecordsIndex为final,则被编译器改成这样
if (index > 100) {
    index = 100;
}

System.out.println(Bean.INT_VALUE);
//编译时会被优化成下面这样:
System.out.println(100);
所以正常的使用方式还是获取原来的值,获得修改后的final常量的值需要用field.get(null)这样的方式。

      总体来讲,改基本类型的final常量的用处还是不大,如果是非基本类型常量,则有实际意义。
  评论这张
 
阅读(2532)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017