Setting a private static target field with reflection

Based on Change my personal static final field using Java reflection , I tried to set my personal static final field.

(I know this is terribly hacked, but this question is not about the quality of the code, but the reflection of Java.)

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 } } 

Will print

 1 

I tried this with OpenJDK 6 and 7 and Oracle 7.

I do not know what the Java guarantee gives. But if this failed, I thought there would be an Exception (almost all reflection methods throw exceptions).

What's going on here?

+5
source share
1 answer

Java inlines final fields that initialize constant expressions at compile time.

According to the Java Language Specification, any static final * field initialized by an expression that can be evaluated at compile time must be compiled into byte code that "builds" the field value. That is, a dynamic link will not be present inside the Main class, telling it to get the value for A from InterfaceA at run time.

Decompile the bytecode and you will find that the body of getA() just pushes the constant 1 and returns it.


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

+9
source

Source: https://habr.com/ru/post/1200761/


All Articles