Modifying final fields in Java

前端 未结 5 2017
故里飘歌
故里飘歌 2020-12-13 00:07

Let\'s start with a simple test case:

import java.lang.reflect.Field;

public class Test {
  private final int primitiveInt = 42;
  private final Integer wra         


        
5条回答
  •  青春惊慌失措
    2020-12-13 00:17

    This is not an answer, but it brings up another point of confusion:

    I wanted to see if the issue was compile-time evaluation or whether the reflection was actually allowing Java to get around the final keyword. Here's a test program. All I added was another set of getter calls, so there's one before and after each changeField() call.

    package com.example.gotchas;
    
    import java.lang.reflect.Field;
    
    public class MostlyFinal {
      private final int primitiveInt = 42;
      private final Integer wrappedInt = 42;
      private final String stringValue = "42";
    
      public int getPrimitiveInt()   { return this.primitiveInt; }
      public int getWrappedInt()     { return this.wrappedInt; }
      public String getStringValue() { return this.stringValue; }
    
      public void changeField(String name, Object value) throws IllegalAccessException, NoSuchFieldException {
        Field field = MostlyFinal.class.getDeclaredField(name);
        field.setAccessible(true);
        field.set(this, value);
        System.out.println("reflection: " + name + " = " + field.get(this));
      }
    
      public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
        MostlyFinal test = new MostlyFinal();
    
        System.out.println("direct: primitiveInt = " + test.getPrimitiveInt());
        test.changeField("primitiveInt", 84);
        System.out.println("direct: primitiveInt = " + test.getPrimitiveInt());
    
        System.out.println();
    
        System.out.println("direct: wrappedInt = " + test.getWrappedInt());
        test.changeField("wrappedInt", 84);
        System.out.println("direct: wrappedInt = " + test.getWrappedInt());
    
        System.out.println();
    
        System.out.println("direct: stringValue = " + test.getStringValue());
        test.changeField("stringValue", "84");
        System.out.println("direct: stringValue = " + test.getStringValue());
      }
    }
    

    Here's the output I get (under Eclipse, Java 1.6)

    direct: primitiveInt = 42
    reflection: primitiveInt = 84
    direct: primitiveInt = 42
    
    direct: wrappedInt = 42
    reflection: wrappedInt = 84
    direct: wrappedInt = 84
    
    direct: stringValue = 42
    reflection: stringValue = 84
    direct: stringValue = 42
    

    Why the heck does the direct call to getWrappedInt() change ?

提交回复
热议问题