Java の静的最終クラス変数の値はリフレクションを通じて取得できますか?
ベストアンサー1
それは型とコンパイラーによって異なると思います
(よく考えてみると、そうでないほうが良いでしょう)。Sun のコンパイラーはプリミティブ定数をインライン化しますが、クラスからエントリを完全に削除するかどうかはわかりません。調べてみます。
編集:はい、インライン化されていてもアクセスできます。テスト クラス:
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));
}
}
}
出力:
定数: 100 CONST_STRING: 文字列 CONST_OBJECT: xyz
javap -c
出力:
「ReflectionConstantTest.java」からコンパイル パブリッククラスscratch.ReflectionConstantTestはjava.lang.Objectを拡張します{ パブリック スクラッチ.ReflectionConstantTest(); コード: 0: ロード_0 1:invokespecial #1; //メソッド java/lang/Object."":()V 4: 戻る パブリック静的 void main(java.lang.String[]) は java.lang.Exception をスローします。 コード: 0: ビプッシュ100 2: istore_1 3: ldc #2; //文字列文字列 5: アストア2 6: getstatic #3; //フィールド CONST_OBJECT:Ljava/lang/Object; 9: アストア3 10: ldc_w #4; //クラススクラッチ/ReflectionConstantTest 13:invokevirtual #5; //メソッド java/lang/Class.getDeclaredFields:()[Ljava/lang/reflect/Field; 16: アストア4 18: アロード4 20: 配列の長さ 21: iストア5 23: アイコンt_0 24: iストア6 26: iload 6 28: iload 5 30: if_icmpge 90 33: 4をロード 35: iload 6 37: たくさん 38: ストア7 40: ロード7 42: アイコンt_1 43:invokevirtual #6; //メソッド java/lang/reflect/Field.setAccessible:(Z)V 46: getstatic #7; //フィールド java/lang/System.out:Ljava/io/PrintStream; 49: 新しい #8; //クラス java/lang/StringBuilder 52: 重複 53:invokespecial #9; //メソッド java/lang/StringBuilder."":()V 56: アロード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; //文字列: 66:invokevirtual #11; //メソッド java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 69: アロード7 71: 定数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: 6, 1 を加算 87: 26へ進む 90: 戻る 静的 {}; コード: 0: 新しい #8; //クラス java/lang/StringBuilder 3: 重複 4: ldc #17; //文字列xyz 6:invokespecial #18; //メソッド java/lang/StringBuilder."":(Ljava/lang/String;)V 9: putstatic #3; //フィールド CONST_OBJECT:Ljava/lang/Object; 12: 戻る }
はインライン化されていますCONST_INT
が、 とCONST_STRING
(CONST_OBJECT
もちろん) はインライン化されていません。YetCONST_INT
は依然としてリフレクションで使用できます。