2009-05-11 7 views

答えて

55

私はそれがタイプとコンパイラによって異なりますと推測します (2番目の考えでは、それはもっと良いことではありませんでした!)。 Sunのコンパイラはプリミティブ定数をインラインにしますが、クラスからエントリを完全に削除するかどうかはわかりません。私は見つけることができます。

編集:はい、インラインであってもアクセスできます。 Testクラス:

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出力:

 
Compiled from "ReflectionConstantTest.java" 
public class scratch.ReflectionConstantTest extends java.lang.Object{ 
public scratch.ReflectionConstantTest(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."":()V 
    4: return 

public static void main(java.lang.String[]) throws java.lang.Exception; 
    Code: 
    0: bipush 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; //Method java/lang/Class.getDeclaredFields:()[Ljava/lang/reflect/Field; 
    16: astore 4 
    18: aload 4 
    20: arraylength 
    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: astore 7 
    40: aload 7 
    42: iconst_1 
    43: invokevirtual #6; //Method java/lang/reflect/Field.setAccessible:(Z)V 
    46: getstatic  #7; //Field java/lang/System.out:Ljava/io/PrintStream; 
    49: new  #8; //class java/lang/StringBuilder 
    52: dup 
    53: invokespecial #9; //Method java/lang/StringBuilder."":()V 
    56: aload 7 
    58: invokevirtual #10; //Method java/lang/reflect/Field.getName:()Ljava/lang/String; 
    61: invokevirtual #11; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    64: ldc  #12; //String : 
    66: invokevirtual #11; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    69: aload 7 
    71: aconst_null 
    72: invokevirtual #13; //Method java/lang/reflect/Field.get:(Ljava/lang/Object;)Ljava/lang/Object; 
    75: invokevirtual #14; //Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 
    78: invokevirtual #15; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
    81: invokevirtual #16; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    84: iinc 6, 1 
    87: goto 26 
    90: return 

static {}; 
    Code: 
    0: new  #8; //class java/lang/StringBuilder 
    3: dup 
    4: ldc  #17; //String xyz 
    6: invokespecial #18; //Method java/lang/StringBuilder."":(Ljava/lang/String;)V 
    9: putstatic  #3; //Field CONST_OBJECT:Ljava/lang/Object; 
    12: return 

} 

あなたはCONST_INTがインライン化されていることを見ることができますが、CONST_STRINGCONST_OBJECT(もちろん)がありません。まだCONST_INTはまだ反映されています。

+0

これは、おかげで私の問題を解決しました!私はなぜf.setAccessible(true)を呼び出さなければならないのか不思議です。静的修飾子を最初から利用できない点は何ですか? – gsingh2011

+0

@ gsingh2011:必要なのは、プライベート定数でさえ、リフレクションによってアクセスできることを実証することです(この例の3つの定数はprivateと宣言されていることがわかります)。パブリック定数は既にアクセス可能なため、アクセス可能に設定する必要はありません。 –

+0

ああ、そうです。私は自分のフィールドに公開/非公開の修飾子を提供しなかったために私の問題が発生したことを認識した後、自分のコードをパッケージにリファクタリングしました。とにかく応答に感謝します。 – gsingh2011

1

オープンの場合ソースライブラリは、あなたができる別のクラスでは

FieldUtils.readDeclaredStaticField

public class Test { 
    public final static String CONSTANT="myConstantValue"; 
} 

を使用することができ、あなたのプロジェクトに許可されています

Object value = FieldUtils.readDeclaredStaticField(Test.class, "CONSTANT"); 
System.out.println(value); 

「myConstantValue」がコンソールに表示されます。

0

名前と値を取得するだけで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); 
} 
関連する問題