Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Java static final variable value through reflection

People also ask

Can we access final variable in static method?

We cannot directly access the instance variables within a static method because a static method can only access static variables or static methods.

How do I change the value of the final static variable in Java?

In Java, non-static final variables can be assigned a value either in constructor or with the declaration. But, static final variables cannot be assigned value in constructor; they must be assigned a value with their declaration.

How do you call a static variable from another class?

Static variables can be accessed by calling with the class name ClassName. VariableName. When declaring class variables as public static final, then variable names (constants) are all in upper case. If the static variables are not public and final, the naming syntax is the same as instance and local variables.

Can we change the value of static final variable?

The static keyword means the value is the same for every instance of the class. The final keyword means once the variable is assigned a value it can never be changed.


I would guess that it depends on the type and the compiler (on second thought, it had sure better not!). Sun's compiler inlines primitive constants, but I don't know if they remove the entry from the class entirely. I'll find out.

Edit: Yes, you can still access them even if they are inlined. Test class:

public class ReflectionConstantTest {
    private static final int CONST_INT = 100;
    private static final String CONST_STRING = "String";
    private static final Object CONST_OBJECT = new StringBuilder("xyz");
    public static void main(String[] args) throws Exception {
        int testInt = CONST_INT;
        String testString = CONST_STRING;
        Object testObj = CONST_OBJECT;
        for (Field f : ReflectionConstantTest.class.getDeclaredFields()) {
            f.setAccessible(true);
            System.out.println(f.getName() + ": " + f.get(null));
        }
    }
}

Output:

CONST_INT: 100
CONST_STRING: String
CONST_OBJECT: xyz

javap -c output:

Compiled from "ReflectionConstantTest.java"
public class scratch.ReflectionConstantTest extends java.lang.Object{
public scratch.ReflectionConstantTest();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   return

public static void main(java.lang.String[])   throws java.lang.Exception;
  Code:
   0:   bipush  100
   2:   istore_1
   3:   ldc     #2; //String String
   5:   astore_2
   6:   getstatic       #3; //Field CONST_OBJECT:Ljava/lang/Object;
   9:   astore_3
   10:  ldc_w   #4; //class scratch/ReflectionConstantTest
   13:  invokevirtual   #5; //Method java/lang/Class.getDeclaredFields:()[Ljava/lang/reflect/Field;
   16:  astore  4
   18:  aload   4
   20:  arraylength
   21:  istore  5
   23:  iconst_0
   24:  istore  6
   26:  iload   6
   28:  iload   5
   30:  if_icmpge       90
   33:  aload   4
   35:  iload   6
   37:  aaload
   38:  astore  7
   40:  aload   7
   42:  iconst_1
   43:  invokevirtual   #6; //Method java/lang/reflect/Field.setAccessible:(Z)V
   46:  getstatic       #7; //Field java/lang/System.out:Ljava/io/PrintStream;
   49:  new     #8; //class java/lang/StringBuilder
   52:  dup
   53:  invokespecial   #9; //Method java/lang/StringBuilder."":()V
   56:  aload   7
   58:  invokevirtual   #10; //Method java/lang/reflect/Field.getName:()Ljava/lang/String;
   61:  invokevirtual   #11; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   64:  ldc     #12; //String :
   66:  invokevirtual   #11; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   69:  aload   7
   71:  aconst_null
   72:  invokevirtual   #13; //Method java/lang/reflect/Field.get:(Ljava/lang/Object;)Ljava/lang/Object;
   75:  invokevirtual   #14; //Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
   78:  invokevirtual   #15; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   81:  invokevirtual   #16; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   84:  iinc    6, 1
   87:  goto    26
   90:  return

static {};
  Code:
   0:   new     #8; //class java/lang/StringBuilder
   3:   dup
   4:   ldc     #17; //String xyz
   6:   invokespecial   #18; //Method java/lang/StringBuilder."":(Ljava/lang/String;)V
   9:   putstatic       #3; //Field CONST_OBJECT:Ljava/lang/Object;
   12:  return

}

You can see that CONST_INT is inlined, but CONST_STRING and CONST_OBJECT (of course) are not. Yet CONST_INT is still available reflectively.


Yes. (Only there is no such thing as static, instance. It's static, non-instance.)

> If the underlying field is a static field, the obj argument is ignored; it may be null.

(include standard warning that most uses of reflection are a bad idea)


If open-source libraries are allowed on your project you can use

FieldUtils.readDeclaredStaticField

public class Test {
    public final static String CONSTANT="myConstantValue";
}

In another class you can use:

Object value = FieldUtils.readDeclaredStaticField(Test.class, "CONSTANT");
System.out.println(value);

You will see "myConstantValue" in the console.