[英]Accessing Java static final variable value through reflection
可以通过反射检索Java静态最终类变量的值吗?
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. Sun的编译器内联了原始常量,但我不知道他们是否完全从类中删除了该条目。 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: 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_INT
is inlined, but CONST_STRING
and CONST_OBJECT
(of course) are not. 您可以看到CONST_INT
是内联的,但CONST_STRING
和CONST_OBJECT
(当然)不是。 Yet CONST_INT
is still available reflectively. 然而, CONST_INT
仍然具有反思性。
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; >如果基础字段是静态字段,则忽略obj参数; it may be null. 它可能是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 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”。
Just getting the name and value does not require setAccessible(true). 只是获取名称和值不需要setAccessible(true)。 Here's a useful example when you have to deal with constants declared in an interface, and want the symbolic names: 当你必须处理在接口中声明的常量并且想要符号名称时,这是一个有用的例子:
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.