通过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); }