Please refer to the below code.
When I run the code, I am able to change the value of a final non-static variable. But if I try to change the value of a final static variable then it throws java.lang.IllegalAccessException
.
My question is why doesn't it throw an exception in case of non-static final variable also or vice versa. Why the difference?
import java.lang.reflect.Field;
import java.util.Random;
public class FinalReflection {
final static int stmark = computeRandom();
final int inmark = computeRandom();
public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
FinalReflection obj = 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);
instanceFinalField.set(obj, 100);
System.out.println(obj.inmark);
staticFinalField.set(FinalReflection.class, 101);
System.out.println(FinalReflection.stmark);
}
private static int computeRandom() {
return new Random().nextInt(5);
}
}
For final, it can be assigned different values at runtime when initialized.
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.
The javadoc is clear:
From a JLS perspective, the exact behaviour of how reflection should work is not specified, but in JLS 17.5.4:
One workaround is to remove the final modifier through reflection.
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 thefinal
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 afinal
field with those modifications of afinal
field that do not take place in the constructor. More on this is also explained in this similar question.