static block vs initializer block vs constructor i

2019-06-06 23:06发布

This question already has an answer here:

i find this example and i want to understand the logic behind it ? how constructors and static blocks and initializer blocks works in inheritance ? in which stage each one is called ?

public class Parent {

    static {
        System.out.println("i am Parent 3");
    }

    {
        System.out.println("i am parent 2");
    }

    public Parent() {
        System.out.println("i am parent 1");
    }

}

public class Son extends Parent {

    static {System.out.println("i am son 3");}
    {System.out.println("i am son 2");}

    public Son() {
        System.out.println("i am son 1");
    }

    public static void main(String[] args) {
        new Son();
    }
}

the output is :

i am Parent 3
i am son 3
i am parent 2
i am parent 1
i am son 2
i am son 1

4条回答
再贱就再见
2楼-- · 2019-06-06 23:22

A static block is called once, when the class is loaded and initialized by the JVM. An instance initializer is executed when an instance of the class is constructed, just like a constructor.

Static and Instance initializers are described in the Java Language Specification

查看更多
Melony?
3楼-- · 2019-06-06 23:34

Static block gets executed when the class is loaded into JVM whereas constructor block gets executed when an instance is created.

A static initializer is the equivalent of a constructor in the static context. You will certainly see that more often than an instance initializer.

查看更多
不美不萌又怎样
4楼-- · 2019-06-06 23:37

You need to know that

  1. first instruction in constructor is invoking constructor of its parent class super(params) or if you want to use default constructor super(). In case of default constructor you don't have to write it explicitly.
  2. code in initializer block is moved to every constructor right after super(...) call
  3. static block is executed when class is initialized which is done after it is fully loaded (with its parent classes) by JVM.

So classes are compiled into classes similar to this.

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

    public Parent() {
        super();
        {
            System.out.println("Parent initializer block");
        }
        System.out.println("Parent constructor");
    }

}

public class Son extends Parent {

    static {
        System.out.println("Son static block");
    }

    public Son() {
        super();
        {
            System.out.println("Son initializer block");
        }
        System.out.println("Son constructor");
    }

    public static void main(String[] args) {
        new Son();
    }
}

To be able to execute main method from Son class JVM needs to load code of this class (and classes it extends). After class is fully loaded JVM initialize its static content which involves executing static blocks (yes, there can be more then one static blocks in one class). To fully load Son class JVM needs to know details about its parent class so it will fully load Parent class before Son which means it will also execute its static blocks before static blocks in Son class.

So output will look like:

  • Parent static block
  • Son static block

Now in main method you are invoking Son class constructor via new Son() which code looks like

super();
{
    System.out.println("Son initializer block");
}
System.out.println("Son constructor");

Since its super() refer to Parent class constructor, which is

super();// this will invoke Object constructor since Parent 
        // doesn't extend anything (which means it extends Object class)
{
    System.out.println("Parent initializer block");
}
System.out.println("Parent constructor");

as result you will see

  • Parent initializer block
  • Parent constructor

This handles Parent#constructor() executed with super() so next you will see code from Son constructor after super() which will generate

  • Son initializer block
  • Son constructor

To see that classes will be loaded even before you use Son constructor or even main method you can just print something before using Son constructor like

System.out.println("ABC                      // before new Son()");
new Son();

which will result in

Parent static block
Son static block
ABC                      // before new Son()
Parent initializer block
Parent constructor
Son initializer block
Son constructor
查看更多
仙女界的扛把子
5楼-- · 2019-06-06 23:42

Static block called when your class is loaded and your class is first loaded by classloader in jvm so first they get executed

then you create object so your parent init block is called then your parent constructor due to constructor chaining in java then derived class init block then derived class constructor

查看更多
登录 后发表回答