之前认为static final的变量是不可改变的,通过反射也是无法修改的,但是这个变量并不是不可以改变的,这里先给出结论:
被static final修饰的 基本数据类型和String是无法通过反射进行修改的,但是其他类型(比如基本类型的包装类)则是可以通过反射改变。
演示代码
private static void setFinalStatic(Field field, Object newValue) throws NoSuchFieldException, IllegalAccessException {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
这里修改 static final 值得原理是,将这个 Field 的 FieldAccessor 的 final 给去掉了,否则在
field.set(null, newValue);
的时候, 就会检查 final 而导致失败
全部代码如下:
public class StaticFinalTest {
public static void main(String[] args) throws Exception {
Field number = Test.class.getDeclaredField("NUMBER");
setFinalStatic(number, 3);
System.out.println(Test.getNumber());
}
private static void setFinalStatic(Field field, Object newValue) throws NoSuchFieldException, IllegalAccessException {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
}
class Test{
private static final Integer NUMBER = 1;
public static Integer getNumber() {
return NUMBER;
}
}