web-dev-qa-db-ja.com

静的クラスの初期化はいつ行われますか?

静的フィールドはいつ初期化されますか?クラスをインスタンス化することは決してないが、静的フィールドにアクセスする場合、プライベートスタティックフィールドをインスタンス化するために使用されるすべての静的ブロックとプライベート静的メソッドは、その時点で(順番に)呼び出されますか?

静的メソッドを呼び出すとどうなりますか?すべての静的ブロックも実行しますか?メソッドの前に?

107
Tony R

通常、クラスの静的初期化は、次のイベントのいずれかが最初に発生する直前に発生します。

  • クラスのインスタンスが作成され、
  • クラスの静的メソッドが呼び出され、
  • クラスの静的フィールドが割り当てられます。
  • 非定数の静的フィールドが使用されている、または
  • 最上位クラスの場合、クラス内に字句的にネストされたassertステートメントが実行されます1

JLS 12.4.1 を参照してください。

Class.forName(fqn, true, classLoader) または短縮形 Class.forName(fqn))を使用して、クラスを強制的に初期化することもできます(まだ初期化されていない場合)。


1-Java 6からJava 8までのJLSに最後の箇条書きがありましたが、明らかに仕様の間違いでした。最終的に修正されました。 Java 9 JLS: source を参照してください。

150
Stephen C

静的フィールドは、静的初期化子とその静的フィールドの初期化を含む、クラスのロード(ロード、リンク、および初期化)の 初期化 「フェーズ」で初期化されます。静的初期化子は、クラスで定義されているテキストの順序で実行されます。

例を考えてみましょう:

public class Test {

   static String sayHello()  {
      return a;
   }

   static String b = sayHello(); // a static method is called to assign value to b.
                                 // but its a has not been initialized yet.

   static String a = "hello";

   static String c = sayHello(); // assignes "hello" to variable c

    public static void main(String[] arg) throws Throwable {
         System.out.println(Test.b); // prints null
         System.out.println(Test.sayHello()); // prints "hello"
    }
}

Test.bは、nullが静的スコープで呼び出されたときに、静的変数sayHelloが初期化されなかったため、aを出力します。

13
naikus

はい、クラスに初めてアクセスする前に、すべての静的初期化子が実行されます。それが他の方法であれば、私はそれをバグと呼びます。

1
Nikita Rybak