6

以下を含むクラスを作成しました。

  1. static final変数
  2. staticSystem.out.println()ステートメントを含む初期化ブロック

static final別のクラスから変数を呼び出すと、staticブロックは実行されません。

私の知る限りstatic、クラスがメモリに読み込まれると、初期化ブロックが実行されます。

この場合、メモリ レベルで何が起こっているのでしょうか。

クラスがメモリにロードされていませんか? そうでない場合、他のクラスはどこでfinal static変数のアドレスを取得しますか?


ケース 1: staticブロックが実行されない

class Test2 {
    static final int a = 20;

    static {
        System.out.println("one");
    }
}

ケース 2: staticブロック実行される

class Test2 {
    static final int a;

    static {
        a = 20;
        System.out.println("one");
    }
}

出力

class Test {
    public static void main(String[] args) {
        System.out.println(Test2.a);
    }
}
  • ケース 1:

    20
    
  • ケース 2:

    one
    20
    

では、両方のレベルで何が起こっているのでしょうか?

4

2 に答える 2

12

私の推測では、フィールドはプリミティブ型またはのいずれかStringであり、コンパイル時の定数式で初期化されています。

定数式で初期化された static final フィールド (およびそのようなフィールドのみ) の場合、クラスの初期化を引き起こす static フィールドを経由するのではなく、フィールドを参照するすべてのコードに定数値が組み込まれます。ただし、「定数式」の部分は重要です。これは、小さなテスト アプリで確認できます。

class Fields {
    
    public static final String CONSTANT = "Constant";
    public static final String NON_CONSTANT = new String("Non-constant");
    
    static {
        System.out.println("Initializing");
    }
}

public class Test {
    public static void main(String arg[]) {
        System.out.println(Fields.CONSTANT);
        System.out.println(Fields.NON_CONSTANT);
    }
}

出力は次のとおりです。

Constant
Initializing
Non-constant

定数フィールドへのアクセスには初期化は必要ありませが、非定数フィールドへのアクセスには初期化が必要です。final 以外のフィールドを使用しても同じ効果があります。基本的に、定数としてカウントされなくなります。

「これは定数です」という情報は、フィールドを宣言するクラスに組み込まれます。たとえば、javap -c Fields次の 2 つのフィールドが表示されます。

public static final java.lang.String CONSTANT;
  flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
  ConstantValue: String Constant

public static final java.lang.String NON_CONSTANT;
  flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL

フィールド メタデータから欠落しているフィールド メタデータのConstantValue部分に注意してください。CONSTANTNON_CONSTANT

定数式を構成する要素の詳細については、JLS のセクション 15.28 を参照してください。

JLS のセクション 12.4.1 は、クラスがいつ初期化されるかを指定します。

クラスまたはインターフェイスの型 T は、次のいずれかが最初に発生する直前に初期化されます。

  • T はクラスであり、T のインスタンスが作成されます。

  • T はクラスであり、T によって宣言された静的メソッドが呼び出されます。

  • T によって宣言された static フィールドが割り当てられます。

  • T によって宣言された静的フィールドが使用され、そのフィールドは定数変数ではありません (§4.12.4)

  • T は最上位クラス (§7.6) であり、T (§8.1.3) 内で語彙的にネストされた assert ステートメント (§14.10) が実行されます。

(私のものを強調してください。)

于 2013-09-25T06:10:49.587 に答える
11
  1. static final フィールドはコンパイル時の定数であり、その値はその元への参照なしで宛先クラスにハードコーディングされます。

  2. したがって、メイン クラスはフィールドを含むクラスのロードをトリガーしません。

  3. したがって、そのクラスの静的初期化子は実行されません。

final魔法が定義から取り除かれているのを見てください。静的イニシャライザの実行が表示されます

于 2013-09-25T05:56:15.680 に答える