Question

Can the value of a final static field change when it refers to a method? For example, if you run the following code:

private static final String example = Example.getExampleString();

Can the value of example change when the method getExampleString() returns something different?

Was it helpful?

Solution

The code you have in your question is an initializer. As a result, Example.getExampleString() is called once when the variable is first defined in memory, and after that, example will contain the value the function returned that one time it was called.

So if you run your program twice, the variable could have a different value for each run, but once the variable is set, it can't be changed while the program is running.

As an example, try this:

import java.util.Random;

public class VarTest {
    private static final Random rng = new Random();
    private static final String example = Integer.toString(rng.nextInt());

    public static void main(String[] args) {
        System.out.println(example);
        System.out.println(rng.nextInt());
        System.out.println(rng.nextInt());
        System.out.println(example);
    }
}

If you run this program, you'll see that nextInt returns different values with each call, but example remains constant within the program. If you run it a second time, example can be different than the last time you ran it, but example still doesn't change during runtime. (You may need to wait a few seconds or minutes between runs to see different values of example because of how Random works.)

OTHER TIPS

No, it cannot. example is final and initialized to the reference value returned by getExampleString() when the class is initialized. Since it is final, the variable cannot be reassigned with another reference value.

You can do it through reflection, but that has nothing to do with the method you are invoking in the initialization expression.

Forgetting the part that the variable is final static, the method itself is called only once to provide a String.

Since you asked if it is possible then answer is unfortunately yes.
But you need to remember that purpose of final fields it to let programmer set its value only once so you should never try to change it.
Below is example of how you can do it, but this is only for (bad)education purpose.


Since result of Example.getExampleString() can't be considered compile-time constant expression then this example is not considered constant variable so its value will not be inlined in code which will use example. So based on this answer you can do something like

class Example {

    private static final String example = Example.getExampleString();

    private static String getExampleString() {
        return "foo";
    }

    static void setFinalStatic(Field field, Object newValue) throws Exception {
        field.setAccessible(true);

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

        field.set(null, newValue);
    }

    public static void main(String[] args) throws Exception {
        System.out.println(Example.example);
        setFinalStatic(Example.class.getDeclaredField("example"), "bar");
        System.out.println(Example.example);
    }
}

which will return

foo
bar

So as you can see in this case it was possible to change value of example field.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top