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


110

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

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


回答:


156

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

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

JLS 12.4.1を参照

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


1-最後の箇条書きは、Java 6からJava 8までのJLSに存在していましたが、仕様に間違いがあるようです。最終的にJava 9 JLSで修正されました。ソースを参照してください。


9
ただし、よくある落とし穴があります。プリミティブとStringは置き換えられ、参照されません。class Other { public static final int VAL = 10; }あるクラスのを参照するとMyClass { private int = Other.VAL; }、そのクラスOtherは読み込まれません。代わりに、コンパイラーはコンパイル時に最終フィールドを単に置き換えます。
Rafael Winterhalter 2013年

6
@RafaelWinterhalter-はい...それは、一定の静的フィールドの場合です。
スティーブンC

2
@RafaelWinterhalter、これはすべての「静的な最終」プリミティブまたはString変数には当てはまりません。定数式によって初期化されたものだけです。
Lew Bloch 2017年

1
はい、staticこれは一般的なケースですが、フィールドは必須ではありません。
Rafael Winterhalter

1
同じプログラミング言語です。はい。
スティーブンC

14

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

例を考えてみましょう:

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"
    }
}

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


6
厳密に言えば、初期化はクラスローディングの「フェーズ」ではありません。実際、一部のクラスロードされる可能性がありますが、アプリケーションが実際に使用しない場合は初期化されません。
スティーブンC

@Stephen Cそうです、私はより良い用語がないためにそれを使用しました。おそらく引用します。
naikus 2010

@StephenCは、クラスのロードが行われている間、静的変数(&メソッド)にメモリを割り当てますが、それらの静的変数はコードで提供された値で初期化されないという意味ですか?ここではb-> sayHello()-> aのように見えたため、「a」はメモリにありますが、値はまだ割り当てられていません。
Shabbir Essaji、2018

基本的にそうです。
スティーブンC

1

はい、静的イニシャライザはすべて、クラスに初めてアクセスする前に実行されます。それ以外の方法であれば、私はそれをバグと呼びます。


初期化せずにクラスを参照する方法があります。
Lew Bloch 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.