When I run the following code:
public class Test {
Test(){
System.out.println("1");
}
{
System.out.println("2");
}
static {
System.out.println("3");
}
public static void main(String args[]) {
new Test();
}
}
I expect to get the output in this order:
1
2
3
but what I got is in reverse order:
3
2
1
Can anyone explain why it is output in reverse order?
================
Also, when I create more than one instance of Test
:
new Test();
new Test();
new Test();
new Test();
static block is executed only at first time.
It doesn't look like anyone stated why the 3 is only printed once explicitly. So I would add that this is related to why it is printed first.
Statically defined code is flagged as being separate from any particular instance of the class. In general, statically defined code can be considered to not be any class at all (of course there's some invalidity in that statement when scoping is considered). Thus that code gets run once the class is loaded, as stated above, as in, it isn't being called when an instance is constructed
Test()
, thus calling the constructor multiple times will not result in the static code being run anymore.The bracketed code containing the 2 gets prepended to the construct, as started above, because it is sort of a precondition to all of the constructors in the class. You don't know what will happen in the constructors for Test, but you are guaranteed that they all start by printing 2. Thus this happens before anything in any specific constructor, and is called every time a(ny) constructor is called.
3 - is a static initializer, it runs once when the class is loaded, which happens first.
2 - is an initializer block, the java compiler will actually copy this into each constructor, so you can share some initialization between contructors if you like. Rarely used.
1 - will be executed when you construct the object, after (3) and (2)..
More information here
Complete Explanation
The order of execution is like,
Explanation
Static block will always be called only once in the very beginning whenever the class is accessed by any means, in your case which is when you run the program. (That is what static block is meant for). It does not depend on instances therefore not called again when new instances are created.
Then the Instance initialization block will be called for each instance created and after that the constructor for each instance created. Because both of them can be used to instantiate the instance.
Is instance initialization block actually called before constructor?
After compilation the code will become,
So you can see, the statement written in instance block itself becomes part of the constructor. Therefore it is executed before the statements already written in the constructor.
From this documentation
It all depends on the order of execution of initialization statements. Your test demonstrates that this order is:
Edit
Thanks for the comments, now I can quote the appropriate part in the JVM specification. Here it is, the detailed initialization procedure.
Because the
static{}
code is run when the class is first initialized within the JVM (i.e. even beforemain()
is called), the instance{}
is called when an instance is first initialized, before it's constructed, and then the constructor is called after all that is done.I‘ve get the bytecode-like code here by ASM .
I think this can answer your question , explaining what happened when a object is created in this occasion.
we can see
LDC "3"
is in the "clinit" , this is a class initializer .The lifetime of a object usually is : loading class -> linking class -> class initialization -> object instantiation -> use -> GC . That's why 3 appears first. And as this is in the class level , not object level , it will appear once as class type will be loaded once . For details , referencing to inside the Java2 Virtual Machine : life time of a type
LDC "2"
and`LDC "1"
is in "init" , the constructor.Reason why it's in this order is : Constructor will first execute some implict instruction such as super constructor and code in the {} of a class , then execute code which's in their construtor explicit.
That's what a compiler will do to the java file.