2015-09-10 35 views

回答

1

该字段只有在编译时间常数时才会“内联” - 请参阅JLS中冗长的定义。

所以它是不够的,它是在宣布时分配。 这不是一个编译时间常数,虽然有效声明:

static final int INT_CONST = compute(); 

static int compute() { 
    return 5; 
} 

只需通过反射,你无法确定该领域的初始化。

要访问类字段的任何值,该类需要首先加载,因此无法阻止静态初始化程序运行。

1

您不能反映这样做,但你可以做到这一点使用字节码工程库像ASM

public class AsmTest { 
    static final int a = 2; // constant 
    static final String b = "string"; // constant 
    static final String c = "foo "+"bar"; // constant: concatenation is allowed 
    static final String d = " foobar ".trim(); // not constant: method called 

    public static Object getFieldConstantValue(Class<?> clazz, final String field) { 
     try(InputStream is = clazz.getResourceAsStream(clazz.getSimpleName()+".class")) { 
      final Object[] value = {null}; 
      new ClassReader(is).accept(new ClassVisitor(Opcodes.ASM5) { 
       @Override 
       public FieldVisitor visitField(int access, String name, String desc, 
         String sig, Object val) { 
        if(name.equals(field)) 
         value[0] = val; 
        return null; 
       } 
      }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); 
      return value[0]; 
     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } 
    } 

    public static void main(String[] args) { 
     for(String name : new String[] {"a", "b", "c", "d"}) { 
      System.out.println(name+"="+getFieldConstantValue(AsmTest.class, name)); 
     } 
    } 
} 

输出:

a=2 
b=string 
c=foo bar 
d=null 
+0

感谢这个,ASM听起来像一个不错的选择。我假设ASM代码不会导致执行静态初始化程序? –

+0

@RobertSales,不,它只是读取它作为'byte []'数组。这样它可以读取任何类,即使它没有加载到应用程序中。 –

相关问题