通过reflection访问Java静态最终伊娃值
可以通过reflection来检索Java静态最终类variables的值吗?
我猜想这取决于types和编译器 (第二个想法,最好不要!)。 Sun的编译器内联原始常量,但我不知道他们是否完全从类中移除了这个入口。 我会发现的。
编辑:是的,即使他们被内联,你仍然可以访问他们。 testing课:
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)); } } }
输出:
CONST_INT:100 CONST_STRING:string CONST_OBJECT:xyz
javap -c输出:
编译自“ReflectionConstantTest.java”
公共类scratch.ReflectionConstantTest扩展java.lang.Object {
public scratch.ReflectionConstantTest();
码:
0:aload_0
1:调用特定的#1; //方法java / lang / Object。“”:()
4:回报
public static void main(java.lang.String [])throws java.lang.Exception;
码:
0:双脚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; //方法java / lang / Class.getDeclaredFields:()[Ljava / lang / reflect / Field;
16:阿斯托4
18:aload 4
20:排练
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:阿七
40:aload 7
42:iconst_1
43:invokevirtual#6; //方法java / lang / reflect / Field.setAccessible:(Z)V
46:getstatic#7; // java / lang / System.out:Ljava / io / PrintStream;
49:新#8; // class java / lang / StringBuilder
52:dup
53:invokespecial#9; //方法java / lang / StringBuilder。“”:()
56:aload 7
58:invokevirtual#10; //方法java / lang / reflect / Field.getName :()Ljava / lang / String;
61:invokevirtual#11; //方法java / lang / StringBuilder.append:(Ljava / lang / String;)Ljava / lang / StringBuilder;
64:ldc#12; //string:
66:invokevirtual#11; //方法java / lang / StringBuilder.append:(Ljava / lang / String;)Ljava / lang / StringBuilder;
69:aload 7
71:aconst_null
72:invokevirtual#13; //方法java / lang / reflect / Field.get:(Ljava / lang / Object;)Ljava / lang / Object;
75:invokevirtual#14; //方法java / lang / StringBuilder.append:(Ljava / lang / Object;)Ljava / lang / StringBuilder;
78:invokevirtual#15; //方法java / lang / StringBuilder.toString :()Ljava / lang / String;
81:invokevirtual#16; //方法java / io / PrintStream.println:(Ljava / lang / String;)V
84:iinc 6,1
87:转到26
90:回报
静态的 {};
码:
0:新#8; // class java / lang / StringBuilder
3:dup
4:ldc#17; //弦乐xyz
6:invokespecial#18; //方法java / lang / StringBuilder。“”:( Ljava / lang / String;)V
9:停止#3; // Field CONST_OBJECT:Ljava / lang / Object;
12:回报
}
你可以看到CONST_INT是内联的,但CONST_STRING和CONST_OBJECT (当然)不是。 然而, CONST_INT仍然是reflection性的。
是。 (只有没有静态,实例这样的东西,它是静态的,非实例。)
>如果底层字段是一个静态字段,则忽略obj参数; 它可能是空的。
(包括标准的警告,大多数reflection的使用是一个坏主意)
如果您的项目允许使用开源库,则可以使用
FieldUtils.readDeclaredStaticField
public class Test { public final static String CONSTANT="myConstantValue"; }
在另一个课堂上,你可以使用:
Object value = FieldUtils.readDeclaredStaticField(Test.class, "CONSTANT"); System.out.println(value);
您将在控制台中看到“myConstantValue”。
获取名称和值不需要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); }