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常量的用处还是不大,如果是非基本类型常量,则有实际意义。