changing final variables through reflection, why difference between static and non-static final variable

独自空忆成欢 提交于 2019-11-30 09:08:56
Narendra Pathai
FinalReflectionobj = new FinalReflection();
System.out.println(FinalReflection.stmark);
System.out.println(obj.inmark);
Field staticFinalField  = FinalReflection.class.getDeclaredField("stmark");
Field instanceFinalField  = FinalReflection.class.getDeclaredField("inmark");
staticFinalField.setAccessible(true);
instanceFinalField.setAccessible(true);

//EXTRA CODE
//Modify the final using reflection
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(staticFinalField, staticFinalField.getModifiers() & ~Modifier.FINAL);


instanceFinalField.set(obj, 100);
System.out.println(obj.inmark);
staticFinalField.set(FinalReflection.class, 101);
System.out.println(FinalReflection.stmark);

This solution does not come without some downsides, it may not work in all cases:

In case a final field is initialized to a compile-time constant in the field declaration, changes to the final field may not be visible, since uses of that final field are replaced at compile time with the compile-time constant.

Another problem is that the specification allows aggressive optimization of final fields. Within a thread, it is permissible to reorder reads of a final field with those modifications of a final field that do not take place in the constructor. More on this is also explained in this similar question.

assylias

The javadoc is clear:

If the underlying field is final, the method throws an IllegalAccessException unless setAccessible(true) has succeeded for this Field object and the field is non-static.

From a JLS perspective, the exact behaviour of how reflection should work is not specified, but in JLS 17.5.4:

Normally, a field that is final and static may not be modified.

One workaround is to remove the final modifier through reflection.

For final, it can be assigned different values at runtime when initialized.

Class Test{    
public final int a;
}

Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t1.a = 20;

Thus each instance has different value of field a.

For static final, all instances share the same value, and can't be altered after first initialized.

Class TestStatic{
   public static final int a;
}

Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t1.a = 20;   // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!