When exactly do normal init blocks execute in java

时间:2015-07-31 19:30:14

标签: java

class Bird {
    {
        System.out.print("b1 ");
    }

    public Bird() {
        System.out.print("b2 ");
    }
}

class Raptor extends Bird {
    static {
        System.out.print("r1 ");
    }

    public Raptor() {
        System.out.print("r2 ");
    }

    {
        System.out.print("r3 ");
    }
    static {
        System.out.print("r4 ");
    }
}

class Hawk extends Raptor {
    public static void main(String[] args) {
        System.out.print("pre ");
        new Hawk();
        System.out.println("hawk ");
    }
}

I'm preparing for Java OCA exam. Above code is from the book I'm studying right now. According to the answer the result should be

r1 r4 pre b1 b2 r3 r2 hawk

while I would expect it to be

pre r1 r4 b1 b2 r3 r2 hawk

taking into consideration these rules:

  1. Static init blocks run when class is first loaded
  2. Normal init blocks run right after all super constructors have run

Could someone please show me step by step how this happens? I can understand r1 and r4 to come before everything but why pre right after them?

3 个答案:

答案 0 :(得分:2)

When the class Hawk is loaded, the class Raptor and Bird must also be loaded because, as they are the superclass(es), they are part of the definition of Hawk. When the class is loaded the static initializers are run. "static" really just means it is part of the class rather than instances of the class.

The next thing the JVM does is begin executing the main method. It is static, so no instance is created yet. That is why 'pre' is printed next.

Then the main method creates an instance of Hawk, which will invoke the constructor. Prior to entry in the constructor method the non-static intializer blocks are executed, along with field initialization (which these classes do not have any), in order in the file.

After this it prints 'hawk' and exits.


PS. When writing code I avoid initializer blocks. It is easier to read the code and understand it later when all the statements are in the constructor method. An exception is to build constant collections (ie Maps) since Java doesn't really support it otherwise (unlike Python or JavaScript syntax for literal maps/dicts/objects).

答案 1 :(得分:1)

first class Hawk should loaded to run main method .but before Hawk get loaded super class Raptor should get loaded .so

first Raptor get loaded and static blocks of Raptorrun and it prints r1 and r4

答案 2 :(得分:1)

  • First instruction in constructor is invoking constructor of its parent class super(params).

  • Code in initializer block is executed after super() call .

  • Static block is executed when it is fully loaded by JVM.

At first class Hawk is loaded.Since it extends Raptor, that class is also loaded.When Raptor is loaded, it executes static blocks in it.

Thus you get r1 r4

After that main method executes.Thus o/p becomes r1 r4 pre.

Then Hawk is loaded.On calling constructor of Hawk,Raptor's constructor is called.Raptor's constrcutor calls Bird's constructor.This loads the Bird class and static block inside Bird is executed followed by construtor.

Thus o/p becomes r1 r4 pre b1 b2

After Bird's constructor finishes, the r3 block is executed and Raptor's constructor finihes.

O/p becomes r1 r4 pre b1 b2 r3 r2 .

And finally last sysout is executed