This question already has an answer here:
-
Use of Initializers vs Constructors in Java
9 answers
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
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
You need to know that
- 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.
- code in initializer block is moved to every constructor right after
super(...)
call
- 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
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
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.