クラスのロードと初期化:Java静的最終変数[重複]

Aug 22 2020

Example.java

public class Example {

    static final int i = 10;
    static int j = 20;
    static {
        System.out.println("Example class loaded and initialized");
    }
}

Use.java

import java.util.Scanner;
public class Use {
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        int ch = 1;
        while(ch != 0) {
            System.out.print("Enter choice: ");
            ch = sc.nextInt();

            if (ch == 1) {
                System.out.println("Example's i = " + Example.i);
            } else if(ch == 2){
                System.out.println("Example's j = " + Example.j);
            }
        }
    }
}

java -verbose:class Use、を使用して実行し、入力を指定すると、1出力は10定数i値になります。しかし、Exampleクラスはまだロードされていません。私は、入力を与えたときしかし、2だけにして Example クラスが冗長出力によって可視ように、JVMにロードされ、その後、実施例内の静的ブロックを実行し、またされるj値が初期化され、その後、プリントの。

私のクエリは次のとおりです。入力の1場合、つまりクラスの静的最終(定数)値がExample別のクラスUseで要求された場合、ExampleそれまでクラスがJVMにロードされなかった場合、その定数値はどこからフェッチされますか?静的ファイナルはいつ、どのようにi初期化され、JVMメモリに格納されましたか?

回答

2 Joni Aug 22 2020 at 17:31

よるJava言語仕様のセクション12.4.1(強調追加):

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

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

  • Tによって宣言された静的メソッドが呼び出されます。

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

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

定数変数を使用して初期化され、最終的な変数である定数式。コードでExample.iは、は定数変数であるため、クラスが読み込まれることはありません。

それで、クラスがロードされていない場合、値comはどこから来ますか?

言語仕様では、コンパイラーがその値をインライン化する必要があります。バイナリ互換性のセクションから13.1:

  1. 定数変数(§4.12.4)であるフィールドへの参照は、コンパイル時に定数変数の初期化子によって示される値Vに解決される必要があります。

    そのようなフィールドが静的である場合、フィールドを宣言したクラスまたはインターフェイスを含め、フィールドへの参照がバイナリファイルのコードに存在してはなりません。このようなフィールドは常に初期化されているように見える必要があります(§12.4.2)。フィールドのデフォルトの初期値(Vと異なる場合)は絶対に守らないでください。