Changing private final fields via reflection

前端 未结 4 1028
鱼传尺愫
鱼传尺愫 2020-11-28 07:20
class WithPrivateFinalField {
    private final String s = \"I’m totally safe\";
    public String toString() {
        return \"s = \" + s;
    }
}
WithPrivateFinal         


        
4条回答
  •  庸人自扰
    2020-11-28 07:45

    This answer is more than exhaustive on the topic.

    JLS 17.5.3 Subsequent Modification of Final Fields

    Even then, there are a number of complications. If a final field is initialized to a compile-time constant 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 compile-time constant.

    But, if you read the paragraph above very carefully, you may find a way around here (set the private final field in the constructor instead of in the field definition):

    import java.lang.reflect.Field;
    
    
    public class Test {
    
      public static void main(String[] args) throws Exception {
        WithPrivateFinalField pf = new WithPrivateFinalField();
        System.out.println(pf);
        Field f = pf.getClass().getDeclaredField("s");
        f.setAccessible(true);
        System.out.println("f.get(pf): " + f.get(pf));
        f.set(pf, "No, you’re not!");
        System.out.println(pf);
        System.out.println("f.get(pf): " + f.get(pf));
      }
    
      private class WithPrivateFinalField {
        private final String s;
    
        public WithPrivateFinalField() {
          this.s = "I’m totally safe";
        }
        public String toString() {
          return "s = " + s;
        }
      }
    
    }
    

    The output is then as follows:

    s = I’m totally safe
    f.get(pf): I’m totally safe
    s = No, you’re not!
    f.get(pf): No, you’re not!
    

    Hope this helps a bit.

提交回复
热议问题