Your expectation is incorrect. A static final int
which is initialized with an integer literal will be a compile-time constant. Compile-time constants get inlined by the bytecode compiler.
It will not be possible to change the value at runtime, or using bytecode modification. The inlining that the bytecode compiler did can't be unwound.
Recompilation of the class and its dependent classes is the only tractable way to change the value of a compile-time constant.
Note this is not just an inconvenient artifact of the Java compiler implementation. This handling of compile-time constants is mandated by the JLS. For example, JLS 17.5.3 says this about trying to change a compile-time constant final
using reflection:
"If a final
field is initialized to a constant expression (§15.28) in the field declaration, changes to the final
field may not be observed, since uses of that final
field are replaced at compile time with the value of the constant expression."
In other words, a reflective API call to change Foo.bar
may appear to succeed, but the actual value that has been inlined doesn't change. In fact, the only code that is likely to see the updated value is code that reads Foo.bar
using reflection!
One possible workaround would be to declare the constant in a way that makes it not a compile-time constant. For example:
class Foo() {
public final static int bar = Integer.parseInt("-1");
}