リフレクションを介してJavaのstatic final変数の値にアクセスする 質問する

リフレクションを介してJavaのstatic final変数の値にアクセスする 質問する

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は依然としてリフレクションで使用できます。

おすすめ記事