http://ljhzzyx.blog.163.com/blog/static/3838031220141011111435161/
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常量的用處還是不大,如果是非基本類型常量,則有實際意義。