1. ホーム
  2. java

静的修飾子と最終修飾子によるJavaの奇妙な動作 [重複] [重複

2023-08-20 19:40:23

質問

私たちのチームでは、いくつかの奇妙な挙動を発見しました。 staticfinal の修飾子があります。これはテストクラスです。

public class Test {

    public static final Test me = new Test();
    public static final Integer I = 4;
    public static final String S = "abc";

    public Test() {
        System.out.println(I);
        System.out.println(S);
    }

    public static Test getInstance() { return me; }

    public static void main(String[] args) {
        Test.getInstance();
    }
} 

を実行すると main というメソッドを実行すると、結果が得られます。

null
abc

と書かれていれば理解できるのですが null の値は、静的なクラスメンバのコードは上から下へ実行されるので、両方の回で書いても理解できます。

なぜこのような動作になるのか、どなたか説明していただけませんか?

どのように解決するのですか?

プログラムを実行したときの手順です。

  1. 実行前 main を実行することができます。 Test クラスは、出現順に静的イニシャライザーを実行して初期化する必要があります。
  2. を初期化するために me フィールドを初期化するために new Test() .
  3. の値を表示します。 I . フィールドの型が Integer であるため、コンパイル時の定数のように見えるもの 4 は計算された値 ( Integer.valueOf(4) ). このフィールドのイニシャライザはまだ実行されておらず、初期値である null .
  4. の値を表示します。 S . コンパイル時の定数で初期化されているので、この値は参照先で焼き付けられ、印刷する abc .
  5. new Test() のイニシャライザは完了です。 I のイニシャライザーが実行されます。

教訓:もしイーガーリー初期化された静的シングルトンに依存しているなら、シングルトン宣言を最後の静的フィールド宣言として配置するか、他のすべての静的宣言の後に発生する静的イニシャライザーブロックに頼りましょう。そうすることで、シングルトンの構築コードに対して、クラスが完全に初期化されているように見えるようになります。