Pages

05 April 2012

Constructors and Static-Instance Code Blocks Run Order in Java

When I deal with an objective of SCJP, I always prefer writing a sample code that is basic enough to show compile time and runtime behaviors and problems. After that, purposely, some modifications helps me to understand the idea behind the code.

While preparing SCJP 6.0, one of the most challenging and easy to understand objective is run order of static-instance code blocks and constructors in inheritance tree. Since it requires good understanding of the concept of class loading, and how classes are created when calling their constructors. I developed the sample code below to infer run order from it.

I wrote two static inner classes A and B (B is subclass of A) inside StaticInstanceBlocksRunOrder class that contains the main method to test. Both of static inner classes has two static and two instance code blocks that helps to understand the runtime execution order of static-instance code blocks.Inheritance between A and B will show the runtime order of constructors and relations between instance code blocks and constructors.

After running the main method in StaticInstaceBlocksRunOrder class; I can analyze the execution flow like this:
  1. StaticInstanceBlocksRunOrder is taken into memory by classloader
    • static code blocks are run in order from top to bottom (first two lines at output)
  2. The main method execution is started("MAIN STARTED" printed)
  3. At "LINE X" static inner classes are loaded
    • first class A is loaded
    • static code blocks of A is run like occured at step 1 (4th and 5th lines are run)
    • second B is loaded
    • static code blocks of B is run (6th and 7th lines are run)
    • constructor of B is called; and it' s initialized in this order
      • parent class' instance blocks
      • parent class' constructor
      • B instance blocks
      • B constructor
  4. Instance of B is printed out (last line)
Infered Rules From the Output:
  • Static blocks run in top-down order after class loading 
  • Static blocks of parent classes are executed before the subclass' static blocks by following inheritance hierarchy from top to down level.
  • Instance blocks run in top-down order before constructor runs
  • Instance blocks and constructors of parent classes are executed before the subclass' ones by following inheritance hierarchy from top to down level.
Note: At "LINE W" the commented out line of code is calling the static method of class B. By enabling this line and commenting out "LINE X" static code blocks execution can be easily figured out.

FIRST STATIC BLOCK-StaticInstanceBlocksRunOrder
SECOND STATIC BLOCK-StaticInstanceBlocksRunOrder
MAIN STARTED
FIRST STATIC BLOCK-A
SECOND STATIC BLOCK-A
FIRST STATIC BLOCK-B
SECOND STATIC BLOCK-B
FIRST INSTANCE BLOCK-A
SECOND INSTANCE BLOCK-A
CONSTRUCTOR-A
FIRST INSTANCE BLOCK-B
SECOND INSTANCE BLOCK-B
CONSTRUCTOR-B
in.indijava.scjp5questions.StaticInstanceBlocksRunOrder$B@11661166

/**
 * @author 0guzhan.blogspot.com
 * */
public class StaticInstanceBlocksRunOrder {

 static {
  System.out.println("FIRST STATIC BLOCK-StaticInstanceBlocksRunOrder");
 }
 
 static class A {
  static {
   System.out.println("FIRST STATIC BLOCK-A");
  }
  
  { 
   System.out.println("FIRST INSTANCE BLOCK-A");
  }
  
  public A() {
   System.out.println("CONSTRUCTOR-A");
  }
  
  static { 
   System.out.println("SECOND STATIC BLOCK-A");
  }
  
  { 
   System.out.println("SECOND INSTANCE BLOCK-A");
  }
 }
 
 static class B extends A{
  static {
   System.out.println("FIRST STATIC BLOCK-B");
  }
  
  { 
   System.out.println("FIRST INSTANCE BLOCK-B");
  }
  
  public B() {
   System.out.println("CONSTRUCTOR-B");
  }
  
  static { 
   System.out.println("SECOND STATIC BLOCK-B");
  }
  
  { 
   System.out.println("SECOND INSTANCE BLOCK-B");
  }
  
  static void any() {
   System.out.println("ANY METHOD IS RUN!");
  }
 }
 
 public static void main(String[] args) {
  System.out.println("MAIN STARTED");
//  B.any();   // LINE W
  A a = new B();  // LINE X
  System.out.println(a);
 }
 
 static {
  System.out.println("SECOND STATIC BLOCK-StaticInstanceBlocksRunOrder");
 }
}