Values of compilation time constants are inlined by compiler.
What does it mean?
Lets say there is private static final String STR = "Foo";
. Here we are sure (using standard language rules, without including reflection since it is a tool that breaks all guarantees language enforces, like: preventing accessing private
members, modifying final
, etc.) that value of STR
should be always "Foo"
and that information is also known at compilation time.
This allows compiler to optimize code like System.out.println(STR);
and remove the need to lookup value of STR
but instead use it directly which will produce same bytecode as if we would write System.out.println("Foo");
(since value is known to compiler and "theoretically" always the same).
So even if we use reflection and reassign new value to STR
it will not affect bytecode which represents System.out.println("Foo");
since it no longer depends on STR
.
In your case
String s= URLEncoder.encode("anyValue", ENCODING);
will be compiled as if you would write it as
String s= URLEncoder.encode("anyValue", "UTF-8");
(since private static final String ENCODING = "UTF-8";
value of ENCODINT
is "UTF-8"
and that is inlined in places where ENCODINT
is being used). So even if you assign new value to ENCODINT
(here "UTF-8") it can't affect bytecode which represents URLEncoder.encode("anyValue", "UTF-8")
since it doesn't use/refer to ENCODING
.
If you want to prevent inlining don't make ENCODING
a compilation time constant. In other words ensure that assigned value will need to be "calculated" at runtime. For instance you can use private static final String ENCODING = "UTF-8".substring(0);
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…