Search code examples
javastaticdefault-constructor

Constructor is called before non-static block?


This is my program:

public class Num2 {

   static
   {
        System.out.println("static block -1");
   }
   int no;
   Num2(int n)
   {
       no=n;
       System.out.println("Num");
   }
   Num2()
   {
        no=0;
        System.out.println("default num");
   }
   {
        System.out.println("Non-static block of num1");
   }
}



class call_by_value2 extends Num2
{
       static
       {
           System.out.println("static block of call by value");
       }  
       {
           System.out.println("non- static block of call by value");
       }
       call_by_value2()
       {   
          System.out.println("Default of call by value");
       }
       static void changeno(Num2 n1,Num2 n2)
       {
          Num2 n=new Num2();
          n=n1;
          n1=n2;
          n2=n;
       }
       public static void main(String[] args)
       {
          System.out.println("Main method");
          call_by_value2 c=new call_by_value2();
       }
 }

The output is:

static block -1
static block of call by value
Main method
Non-static block of num1
default num
non- static block of call by value
Default of call by value

which is desired output because we know that firstly non-static block is called then constructor.But when i modify this program and run it as this:

public class Num2 {

   static
   {
       System.out.println("static block -1");
   }
   int no;
   Num2(int n)
   {
       no=n;
       System.out.println("Num");
   }
   Num2()
   {
       no=0;
       System.out.println("default num");
   }
   {
       System.out.println("Non-static block of num1");
   }
}



class call_by_value2 extends Num2
{
      static
      {
          System.out.println("static block of call by value");
      }  
      {
          System.out.println("non- static block of call by value");
      }
      call_by_value2()
      {   
          super(50);
          System.out.println("Default of call by value");
      }
      static void changeno(Num2 n1,Num2 n2)
      {
          Num2 n=new Num2();
          n=n1;
          n1=n2;
          n2=n;
      }
      public static void main(String[] args)
      {
          System.out.println("Main method");
          call_by_value2 c=new call_by_value2();
      }
}

Now the output is:

static block -1
static block of call by value
Main method
Non-static block of num1
Num
non- static block of call by value
Default of call by value

So my question is if default constructor of callbyvalue2 class which contains super() method runs last how the parameterized constructor of Num2 class gives output before the output of default constructor of callbyvalue2 class?


Solution

  • No, this is what happens when you make a call such as.

    new Num2() ;
    

    1) All variables are initialised with default values (0, null, false, '\u0000') including those inherited from superclasses.

    2) The implicit or explicit superclass constructor is called until the Object class (It is not allowed to pass any local variables or method returns as arguments to the superclass constructor invocation). Note that at this point although the implicit or explicit constructors are called they do not execute any code inside.

    (if u have an empty constructor, the compiler will place an implicit call to the no-args superclass constructor, so it doesn't get to execute anything inside the method until top most superclass constructor is reached, since the first line of code in every constructor will be super() ; whether you put it or not. If the superclass does not have a no-args constructor available then u must explicitly provide one as the first line of code in your subclass constructor e.g. super("a string argument") ;)

    3) When top level superclass constructor is reached, variables declared at that level are assigned with their initialisers (values assign explicitly e.g. int i = 23;), block statements execute before constructors no matter where they are declared in the class and constructors are executed after all non-static blocks execute.

    Point 3 will then execute down the inheritance tree until Num2()

    Example 1 This first example will not compile.

    class Animal{
        Animal(int){
    
        }
    }
    
    class Dog extends Animal
    {
        Dog(){
            // right here compiler will place an implicit call to super() ; not seen, at compile time.
            // since there is no no-args constructor available in class Animal compiler will issue a warning and stop compiling. Remember that a no-args constructor is provided by default ONLY if no other constructor was provided by the programmer. In this example we have a constructor in our superclass that takes an int as argument and so we must explicitly tell the compiler to call super(24);
        }
    }
    

    Example 2

    class Animal{
    
    }
    
    class Mammal extends Animal{
        Mammal(int x){ 
    
        }
    }
    
    class Dog extends Mammal{
        Dog(){
            super(24) ;
        }
    
        Dog(int x){
           super(x) ;
        }
    }
    
    class BullDog extends Dog{
        BullDog(){
            this(24) ;
        }
    
        BullDog(int x){
            super(x) ;
        }
    }
    

    Now if we are to make an instance of BullDog using the no-args constructor the following constructor calls will happen.

    1 BullDog() ;

    2 BullDog(24) ;

    3 Dog(24) ;

    4 Mammal(24) ;

    5 here although nothing seems to exist remember that compiler provides an implicit call to super constructor so here will be a call such as Anima();

    6 here class Animal doesn't seem to have any constructor, however compiler will provide the following no-args constructor with a default call to super which should be the no-args constructor of class Object.

    Animal(){
        super() ;
    }
    

    So 6 would be like Object() ;

    You should now understand why code in any constructor won't execute until the Object constructor is reached and that is because there will alway be a call to the superclass constructor as first line. If you omit it the there better be a no-args constructor in your seperclass so that it works with what the complier provides by default otherwise you must explicitly declare it.