0

I took the reference from Change private static final field using Java reflection and wrote below code to update an String type static final field value:

I have one class which contains an Constant like below:

public final class Constants {

    public static final String ACCEPTED = "A";
}

I tried to update it's value using Java Reflection, like below:

Field field = Constants.class.getDeclaredField("ACCEPTED");
    field.setAccessible(true);

    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

    String newValue = "B";
    field.set(null, newValue);

After updating value by using above code I tested it like below:

String myUpdatedValue = Constants.ACCEPTED;

Here when I inspected Constants.ACCEPTED the value was being showed was "B", but when I inspected myUpdatedValue, it is showing as "A". Can't understand reason. Even when I pass this value to some other method as parameter, at the method call it's "B" but inside the called method it's "A".

Community
  • 1
  • 1
Gaurav Jeswani
  • 4,410
  • 6
  • 26
  • 47

1 Answers1

1

To quote the documentation:

Note: If a primitive type or a string is defined as a constant and the value is known at compile time, the compiler replaces the constant name everywhere in the code with its value. This is called a compile-time constant. If the value of the constant in the outside world changes (for example, if it is legislated that pi actually should be 3.975), you will need to recompile any classes that use this constant to get the current value.

In your situation, Constants.ACCEPTED is such a compile time constant. So when your code is compiled, all the references to Constants.ACCEPTED are in fact replaced with the literal "A". Your code manipulates its value in runtime, but this is already too late.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • Thanks a lot for your above explanation, totally make sense, so any way to get this resolved at runtime? Other than creating a method and returning that String from that method. – Gaurav Jeswani Jan 02 '17 at 09:38
  • 1
    @proudandhonour I guess you could use some form of byte-code manipulation like [javassist](https://jboss-javassist.github.io/javassist/), but I'd consider this very carefully before running of and implementing it. It's a lot of hassle, and often quite fragile, so you need to be 100% sure you **really** want to do this. – Mureinik Jan 02 '17 at 10:27