web-dev-qa-db-ja.com

継承を使用する場合、静的ブロックと初期化ブロックはどの順序で実行されますか?

親と子の2つのクラスがあります

public class Parent {    
    public Parent() {
        System.out.println("Parent Constructor");
    }    
    static {
        System.out.println("Parent static block");    
    }    
    {
        System.out.println("Parent initialisation  block");
    }
}

public class Child extends Parent {    
    {
        System.out.println("Child initialisation block");
    }
    static {
        System.out.println("Child static block");
    }

    public Child() {
        System.out.println("Child Constructor");
    }    
    public static void main(String[] args) {
        new Child();    
    }
}

上記のコードの出力は次のようになります

Parent static block
Child static block
Parent initialization  block
Parent Constructor
Child initialization block
Child Constructor

なぜJavaがこの順序でコードを実行するのですか?実行順序を決定するルールは何ですか?

78
CKR666

プレイにはいくつかのルールがあります

  • 静的ブロックは常にオブジェクトが作成される前に実行されるため、親と子の両方の静的ブロックからの印刷メッセージが表示されるのはこのためです
  • 現在、サブクラス(子)のコンストラクターを呼び出している場合、このコンストラクターは、独自のコンストラクターを実行する前にsuper();を暗黙的に呼び出します。初期化ブロックは、コンストラクターの呼び出し前でも機能するため、最初に呼び出されるのはこのためです。これで、親が作成され、プログラムは同じプロセスを実行する子クラスを作成し続けることができます。

説明:

  1. loaded firstであるため、親の静的ブロックが最初に実行され、クラスがロードされるときに静的ブロックが呼び出されます。
50
Petr Mensik

私は視覚的に学習するので、ここに SSCCE としての順序の視覚的表現があります。

public class Example {

  static {
    step(1);
  }

  public static int step_1 = step(2);
  public int step_6 = step(6);

  public Example() {
    step(8);
  }

  {
    step(7);
  }

  // Just for demonstration purposes:
  public static int step(int step) {
    System.out.println("Step " + step);
    return step;
  }
}

public class ExampleSubclass extends Example {

  {
    step(9);
  }

  public static int step_3 = step(3);
  public int step_10 = step(10);

  static {
    step(4);
  }

  public ExampleSubclass() {
    step(11);
  }

  public static void main(String[] args) {
    step(5);
    new ExampleSubclass();
    step(12);
  }
}

これは印刷します:

Step 1
Step 2
Step 3
Step 4
Step 5
Step 6
Step 7
Step 8
Step 9
Step 10
Step 11
Step 12

staticパーツの順序が重要であることに注意してください。 Examplestaticの順序とExampleSubclassの順序の違いを振り返ります。

また、インスタンスの初期化ブロックは、順序に関係なく、コンストラクターの前に常に実行されることに注意してください。ただし、初期化ブロックとフィールド初期化子の間では順序は重要です。

43
Ben Leggiero

最初に-単純なフローを表示するには、子クラスのみを実行します(extend節をコメントします)。

2番目- Javaの静的ブロックと初期化ブロックのどちらですか? に進み、そこに受け入れられた答えを読みます。

編集:

  1. 実行はSIC方式で行われます-静的、(非静的)初期化子およびコンストラクター。
  2. (非静的)初期化子はすべてのコンストラクターにコピーされます-TOP! (したがって3/4/5/6行)
  3. クラスを初期化する前に、その直接スーパークラスを初期化する必要があります- http://docs.Oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4 (したがって、親の静的ブロックが最初に表示されます)。
10
Raúl
  • 静的初期化ブロックは、クラスのロード時に実行されます。
  • クラス階層では、静的初期化ブロックの実行順序は最上位クラスから始まります。
  • クラスでは、静的ブロックの実行順序は上から下です。
  • 上記の規則は、クラス内の静的ブロックの場所に関係なく適用されます。

(コードでは、最初に親の静的ブロックが実行され、次に子クラスの静的ブロックが実行されます。)

  • インスタンスの初期化ブロックは、super()の呼び出し後に実行されます。コンストラクター内。
    • 常にsuper();は、デフォルトコンストラクターの最初のステートメントです。

子オブジェクトを作成するときのコードでは:

  • Childクラスのデフォルトコンストラクターが実行されます。
  • Super()を呼び出します。コンストラクタ。
  • 次に、スーパークラスコンストラクターが実行されます。
  • Parentクラスはそのsuper()を実行します。コール。
  • その後、Parentクラスのインスタンス初期化ブロックが実行されます(上から下へ)。
  • 次に、コンストラクター内のコードが実行されます(ある場合)。
  • 次に、Childクラスに戻り、Childクラスインスタンスのinitブロックを実行します。
  • 最後に、子コンストラクターのコードが実行されます(存在する場合)。
6

Javaの静的ブロックは、mainメソッドの前に実行されます。 JavaクラスでStaticブロックを宣言すると、クラスのロード時に実行されます。これは静的変数で初期化されます。主にJDBCで使用されます。 Javaの静的ブロックは、クラスがロードされるたびに実行されます。これは、静的初期化ブロックとも呼ばれます。 Javaの静的ブロックは、クラスがメモリにロードされるときに初期化されます。これは、JVMがバイトコードを読み取るタイミングを意味します。初期化は何でもかまいません。変数の初期化、またはそのクラスのすべてのオブジェクトで共有する必要のあるその他のものを指定できます。静的ブロックは、中括弧{}で囲まれた通常のコードブロックであり、静的キーワードが先行します。

そのため、静的ブロックが最初に実行されます。

インスタンス初期化ブロック:クラスのインスタンスが作成されるたびに実行されます。

そのため、クラスのインスタンスが作成されたときに実行される次の初期化ブロック。

その後、コンストラクタが実行されました

5
rohan kamat

これは、認定の準備中に見つけたものです。

クラスを実行すると、最初の静的ブロック/静的変数の初期化が行われます。複数の静的ブロックが存在する場合、表示される順序で実行されますが、

その後、initブロック/インスタンス変数の初期化を実行します。複数のinitブロック/変数の初期化が存在する場合は、出現順に実行します。

その後、コンストラクターを調べます。

3
PRAVEEN PS

オブジェクトがフェーズをどのように進んでいるかを見ることができるビューを備えた、ステップごとのデバッガーでオブジェクト構築プロセスを開始することは非常に役立ちます。これは、より高い視点から視点をクリアするのに非常に役立ちました。 Eclipseは、デバッガーの機能へのステップでこれを支援します。

3
Mihai Savin

調査結果を共有したかっただけです。別のスレッドの回答の1つを読んだところ、静的フィールドは正しくない静的フィールドの前に最初に実行されます。静的フィールドと静的ブロックのどちらが先かによって異なります。以下のコードをご覧ください。物事を視野に入れようとします。

  1. JVMは、そのクラスをロードできるようにpublic static void main(String args [])を持つクラスを探します。
  2. 次に、このクラスの静的フィールドを初期化します(静的ブロックの前に来る場合)。これらのフィールドは、このクラスまたは別のクラスの静的メソッドを呼び出すことができます。このクラスの静的メソッドを呼び出すと、そのメソッドが提供されます。別のクラスの静的メソッドを呼び出すと、そのクラスの静的フィールドまたはブロック(どちらが先かによって異なります)が最初に初期化され、このメソッド呼び出しが提供されます。
  3. 次に、静的ブロックに移動します。
  4. Mainメソッドに戻ります。

    class TestLab {
    static int method(String a) {
        System.out.println("in static method of TestLab" + " Coming from " + a);
        System.out.println("b is " + b);
        return 6;
    }
    
    static int a = method("Line 11");
    static int b = 7;
    
    TestLab() {
        System.out.println("Inside test lab constructor");
    }
    
    static {
        System.out.println("In static block of TestLab");
    }
    
    }
    
    public class Test1 {
    public static void main(String[] args) {
        System.out.println("inside main method of Test 1");
        int a = TestLab.method("Line 26");
    }
    
    // static Test ref=new Test();
    Test1() {
        System.out.println("Default Constructor of Test1");
    }
    
    {
        System.out.println("In instance block of Test1");
    }
    static int d = TestLab.method("Line 37");
    static int e = methodOfTest1();
    static {
        System.out.println("In Static Block of Test1");
    }
    
    static int methodOfTest1() {
        System.out.println("inside static method:mehtodOfTest1()");
        return 3;
    }
    }
    

出力は次のとおりです。

in static method of TestLab Coming from Line 11
b is 0
In static block of TestLab
in static method of TestLab Coming from Line 37
b is 7
inside static method:mehtodOfTest1()
In Static Block of Test1
inside main method of Test 1
in static method of TestLab Coming from Line 26
b is 7
3
pragun

制御フローは

static block-> Initialization block->最後にConstructor。

静的ブロック->この静的ブロックは、コントロールがクラスに来たときに一度だけ実行されます。(JVM Load this class)

初期化ブロック->この初期化ブロックは、クラス用に作成された新しいオブジェクトのたびに実行されます(コンストラクターの2番目のステートメントから実行され、コンストラクターステートメントの後に実行されます-最初のステートメントを記憶しますコンストラクタのSuper()/ this())

コンストラクタ->これは、新しいオブジェクトが作成されるたびに取得されます。

1
Prakash VL

1.Static initブロックは、クラスのロード時に1つだけ実行されます。 2.Initブロックは、クラスのオブジェクトを作成する前に毎回実行されます。

リンク: https://www.youtube.com/watch?v=6qG3JE0FbgA&t=2s

0
Java Tutorial

クラスがJVMにロードされると、静的ブロックが実行されます。初期化ブロックは、オブジェクトが作成されるコンストラクタにコピーされ、オブジェクトの作成前に実行されます。

0
Sunil Kumar Jha