As some sources say, the Java instance initialization blocks are executed whenever instance is created or right before constructor. But imagine this case:
public
There's a specific initialization procedure explained in the JLS, but let me distill the most critical parts:
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.
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.
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...
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
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.
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: