2

I tried to modify private final static variable like this:

    ...try {

        Field f =TargetA.class.getDeclaredField("RECV_TIMEOUT");
        f.setAccessible(true);

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

        f.set(null, 12L);

    } catch (Exception e) {
        e.printStackTrace();//not reach here!
    } ...

    class TargetA{
        private static final long RECV_TIMEOUT = 180000L;
     }

However TargetA.RECV_TIMEOUT is still 180000L, without any Exception. I searched the problem in StackOverflow, but couldn’t find solution.

I guess the Java version1.6 has more restriction in reflection which breaks OO rules. Thanks for your advice!

3 Answers 3

7

You can change the static final field this way and if you look at the value using reflection it will be changed. The problem you have is that the compiler does one and only one optimisation which is to inline constants know at compile time. This means the value can be change, however the places where the constant is used is not changed.

A way around this is to use a wrapper method to "confuse" the compiler, which avoid having to change how you use the constant.

public static final long RECV_TIMEOUT = runtime(180000L);

public static final <T> T runtime(T t) { return t; }
Sign up to request clarification or add additional context in comments.

Comments

5

Modification of final fields via reflection has many limitations. In particular, if final field is initialized by a compile-time constant, its new value may not be observed (JLS 17.5.3 Subsequent Modification of Final Fields).

You can use the following workaround:

class TargetA{
     private static final long RECV_TIMEOUT = defaultTimeout();     

     private static long defaultTimeout() { return 180000L; }
} 

Comments

0

Try to add the following code after your change and you will see that it has changed.

Field e =TargetA.class.getDeclaredField("RECV_TIMEOUT");
e.setAccessible(true);
System.out.println(e.getLong(modifiersField));

However as quoted from Peter

This means the value can be change, however the places where the constant is used is not changed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.