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