通过反射访问Java静态最终变量值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/850148/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Accessing Java static final variable value through reflection
提问by
Can the value of a Java static final class variable be retrieved through reflection?
可以通过反射检索Java静态最终类变量的值吗?
回答by Michael Myers
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.
我猜这取决于类型和编译器(再想一想,最好不要!)。Sun 的编译器内联原始常量,但我不知道他们是否完全从类中删除了条目。我会查明真相的。
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 -coutput:
javap -c输出:
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_INTis inlined, but CONST_STRINGand CONST_OBJECT(of course) are not. Yet CONST_INTis still available reflectively.
你可以看到,CONST_INT内联,但CONST_STRING和CONST_OBJECT(当然)不是。然而CONST_INT仍然可以反射。
回答by Tom Hawtin - tackline
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.
> 如果底层字段是静态字段,则忽略 obj 参数;它可能为空。
(include standard warning that most uses of reflection are a bad idea)
(包括标准警告,大多数反射的用途是一个坏主意)
回答by paskos
If open-source libraries are allowed on your project you can use
如果您的项目允许使用开源库,您可以使用
FieldUtils.readDeclaredStaticField
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.
您将在控制台中看到“myConstantValue”。
回答by Per Lindberg
Just getting the name and value does not require setAccessible(true). Here's a useful example when you have to deal with constants declared in an interface, and want the symbolic names:
仅获取名称和值不需要 setAccessible(true)。当您必须处理在接口中声明的常量并需要符号名称时,这是一个有用的示例:
interface Code {
public static final int FOO = 0;
public static final int BAR = 1;
}
...
try {
for (Field field : Code.class.getDeclaredFields()) {
String name = field.getName();
int value = field.getInt(null);
System.out.println(name + "=" + value);
}
}
catch (IllegalAccessException e) {
System.out.println(e);
}

