Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting private static final field with reflection

Based on Change private static final field using Java reflection, I tried to set a private static final field.

(I know this is terribly hacky, but this question is not about code quality; it's about Java reflection.)

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

class Main {

  static class Foo {
    private static final int A = 1;

    int getA() {
      return A;
    }
  }

  public static void main(String[] args) throws Exception {
    Field modifiers = Field.class.getDeclaredField("modifiers");
    modifiers.setAccessible(true);

    Field field = Foo.class.getDeclaredField("A");
    field.setAccessible(true);
    modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, 2);

    System.out.println(new Foo().getA()); // should print 2
  }

}

This prints

1

I've tried this with OpenJDK 6 and 7, and Oracle 7.

I don't know what guarantees Java reflection gives. But if it failed, I thought there would be an Exception (practically all the reflection methods throw exceptions).

What is happening here?

like image 213
Paul Draper Avatar asked Aug 20 '14 14:08

Paul Draper


People also ask

Can static fields be final?

We can initialize a final static variable at the time of declaration. Initialize inside a static block : We can also initialize a final static variable inside a static block because we should initialize a final static variable before class and we know that static block is executed before main() method.

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.

What is private final static?

private static final will be considered as constant and the constant can be accessed within this class only. Since, the keyword static included, the value will be constant for all the objects of the class. private final variable value will be like constant per object. You can refer the java. lang.

How can a final field be set to a value in Java?

When a field is defined as final , it has to be initialised when the object is constructed, i.e. you're allowed to assign value to it inside a constructor. A static field belongs to the class itself, i.e. one per class. A static final field is therefore not assignable in the constructor which is one per object.


1 Answers

Java inlines final fields that are initialized to constant expressions at compile time.

According to the Java Language Specification, any static final* field initialized with an expression that can be evaluated at compile time must be compiled to byte code that "inlines" the field value. That is, no dynamic link will be present inside class Main telling it to obtain the value for A from InterfaceA at runtime.

Decompile the bytecode and you'll find that the body of getA() simply pushes the constant 1 and returns it.


* - The JavaWorld quote says static final. Kumar points out that the static is not required by the language specification in the definition of a constant variable. I think Kumar is right and JavaWorld is in error.

like image 110
Mike Samuel Avatar answered Sep 19 '22 11:09

Mike Samuel