JAVA initialization blocks

后端 未结 6 1745
谎友^
谎友^ 2021-01-21 18:03

As some sources say, the Java instance initialization blocks are executed whenever instance is created or right before constructor. But imagine this case:

public         


        
相关标签:
6条回答
  • 2021-01-21 18:25

    There's a specific initialization procedure explained in the JLS, but let me distill the most critical parts:

    • What happens in terms of initializing a class is implementation-dependent of the JVM.
    • The super class is initialized before its subclasses (step 7) if the super class has not yet been initialized.
    • Evaluate all static initializers and fields as if they were a single block in textual order. That last part is important; it means that what's seen first is initialized first.

    This is why you see the behavior you do - because Main is a subclass to Foo, it isn't yet initialized, so its static block isn't been evaluated at that moment.

    Consequently, Main's constructor isn't executed until after Foo's constructor, since there is an implicit call to super() in the subclass.

    0 讨论(0)
  • 2021-01-21 18:25

    The last statement is incorrect. Main() is executed after Foo(), because a class constructor is executed after its super constructor has finished. For more details see this part of the spec, which deals with implicit and explicit super constructor calls.

    0 讨论(0)
  • 2021-01-21 18:28
            new Main(); 
    

    the above state ment will first goto Main(). But before execution of anything in Main(), super() is called. So, Foo() is called. Now, in Foo() a check is made to see instance initialization block. So, you get. "Foo init" . Next the statements in Foo() are executed. So, you get- "Foo constr". Next the control is returned to Main() which now checks whether an initialization block exists for Main class. So, "Main Init" is printed.. then other statements of Main() are printed. The definition is right.. The understanding.. well... depends on how you see it...

    0 讨论(0)
  • 2021-01-21 18:35

    No. The initialization blocks are copied directly into the constructor(s). Obviously there is an implicit super in there as well. So your example becomes

    public class Foo {
      public Foo()
      {
        {System.out.println("Foo init");} // initializer.
        {System.out.println("Foo constr");}
      }
    }
    
    public class Main extends Foo {
      public Main()
      {  
        super(); // super constructor.
        {System.out.println("Main init");} // initializer.
        {System.out.println("Main constr");}
      }
      public static void main(String[] args) {
        new Main();
      }
    }
    

    Which explains your observed behavior of

    Foo init
    Foo constr
    Main init
    Main constr
    
    0 讨论(0)
  • 2021-01-21 18:38

    See how this code works internally :

    class Foo {
    
        {System.out.println("Foo init");}
    
        public Foo()
        {
    
            {System.out.println("Foo constr");}
        }
    }
    
    
    
    class Main extends Foo {
    
        {System.out.println("Main init");}
    
        public Main()
        {
    
            {System.out.println("Main constr");}
        }
        public static void main(String[] args) {
    
            new Main();
        }
    }
    

    Step 1 : The JVM calls the main() method of Main class

    Step 2 : Constructor Main() have internally super() which is given by JVM if you are not using this(), hence super will call super class constructor i.e Foo() of super class.

    Step 3 : Now before calling the Foo of super class, the JVM will check is there any IIB i.e instance initialization Block, hence, "Foo init" will be printed before printing the "Foo constr"

    Now output till now is :

    Foo init 
    Foo constr
    

    Step 4: Our control come back to the current constructor and again before execution the current construstor JVM will call IIB i.e instance initialization Block and "Main init" will be printed. Then finally "Main constr"

    So Finally out is :

    Foo init
    Foo constr
    Main init
    Main constr
    

    Actually the first call of any Constructor is always Super() or this(). you are creating new object using new Main(); and of course this will give call to constructor, Constructor is always called to initialize the object.

    0 讨论(0)
  • 2021-01-21 18:50

    The code is converted by compiler to something like this:

    public class Main extends Foo {
      void _init()
      {System.out.println("Main init");}
    
      public Main()
      {
        super();
        _init();
        {System.out.println("Main constr");}
      }
    
    }
    

    The main rules are:

    • super() is called before any initialization code of the current class
    • initializer blocks are called before the body of the constructor
    0 讨论(0)
提交回复
热议问题