2015-09-10 34 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 []'數組。這樣它可以讀取任何類,即使它沒有加載到應用程序中。 –

相關問題