Posts Tagged ‘constructor chaining’

The following is a conversation that I was having with myself a few days ago while revisiting some old Java concepts.

What is constructor chaining?

When we create an object in Java, all the constructors in the inheritance hierarchy are called and run. This is known as constructor chaining.

Can you show me an example?

Yes.

import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone
{
  class Parent {
    public Parent() {
      System.out.println("This is parent");
    }
  }

  class Child extends Parent {
    public Child() {
      System.out.println("This is child");
    }
  }

  public static void main (String[] args)
  {
    Ideone one = new Ideone();
    Child c = one.new Child();
  }
}

If you run the above example, you will see the following output –

This is parent
This is child

As you can see, the compiler implicitly put a call to the no-arg constuctor of the parent from the child, which resulted in the above output.

What will happen if the parent class does not have any constructor?

Each and every class in Java has a constructor. If you do not write one explicitly, then the compiler will provide a no-arg constructor by default.

What will happen is the parent class does not have a no-arg constructor, like this –

import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone
{
  class Parent {
    public Parent(String hello) {
      System.out.println(hello);
    }
  }

  class Child extends Parent {
    public Child() {
      System.out.println("This is child");
    }
  }

  public static void main (String[] args)
  {
    Ideone one = new Ideone();
    Child c = one.new Child();
  }
}

A compile-time error will be issued if you do not explicitly call any of the available parent constructors, because in this case the compiler tries to automatically call the no-arg constructor of the parent, and since it does not have any, an error will occur.

But I thought the compiler will always define the no-arg constructor for me?

Nope.

The moment you defined a constructor for the parent by yourself, the compiler stopped interfering. Which means, now it will not automatically define the default constructor for you. If you want a no-arg constructor now, you will have to define one by yourself.

So if I now explicitly define a no-arg constructor in the parent, the error will be resolved?

That is one of the two ways to solve it. The other one is given below –

import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone
{
  class Parent {
    public Parent(String hello) {
      System.out.println(hello);
    }
  }

  class Child extends Parent {
    public Child() {
      super("Hi Parent!");
      System.out.println("This is child");
    }
  }

  public static void main (String[] args)
  {
    Ideone one = new Ideone();
    Child c = one.new Child();
  }
}

Now you will not get any error!

Using super you can explicitly call a parent constructor, providing the required arguments and thus choosing an appropriate overloaded version. This is exactly how the compiler called the parent constructors in the first and the second examples, except the super call was invisible to us. The compiler automatically put it when it compiled our code.

You need to be aware of one thing though – the super call should be the first statement of the child constructor, otherwise the compiler will throw an error. As a consequence, you cannot use super() and this() in the same constructor at the same time.

What is this()?

You use this() to call the constructor of the same class. Usually you use it to call an overloaded version of the constructor which contains common initialization logic for the class, like below –

import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone
{
  class AClass {
    public AClass() {
      this("Say Hi!");
      System.out.println("This is default");
    }

    public AClass(String hi) {
      System.out.println(hi);
      System.out.println("This is with one arg");
    }
  }

  public static void main (String[] args)
  {
    Ideone one = new Ideone();
    AClass c = one.new AClass();
  }
}

If you run the above example, you will see –

Say Hi!
This is with one arg
This is default

 

If I use this() inside a constructor to call another constructor, will the parent constructor be called twice?

Nope –

import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone
{
  class Parent {
    public Parent() {
      System.out.println("Greetings, underlings!");
    }
  }

  class Child extends Parent {
    public Child() {
      this("Hi single-arg child!");
      System.out.println("This is no-arg child");
    }

    public Child(String sayHi) {
      System.out.println(sayHi);
      System.out.println("This is single-arg child");
    }
  }

  public static void main (String[] args) throws java.lang.Exception
  {
    Ideone one = new Ideone();
    Child c = one.new Child();
  }
}

The output of the above program is

Greetings, underlings!
Hi single-arg child!
This is single-arg child
This is no-arg child

 

We know that Object is implicitly extended by each and every class in Java. Does that mean its no-arg constructor is also invoked during constructor chaining?

Yes, that’s right. Every constructor chain ends with a call to the no-arg constructor of Object.

I feel sleepy. It will be nice to have a summary of our conversation at this point.

Sure.

  • When the parent has no/only the default no-arg constructor –
    1. If the child constructor does not explicitly invoke the parent constructor, then the compiler inserts one call to the default parent constructor as the first line of the child constructors.
    2. If the child explicitly calls the parent constructor, then no automatic call to parent constructor is issued.
  • When the parent has default/no-arg constructor as well as other overloaded constructor(s) –
    1. If the child constructor does not explicitly invoke the parent constructor, then the compiler inserts one call to the default parent constructor as the first line of the child constructors.
    2. If the child explicitly calls any of the parent constructors (does not matter which one) then no automatic calls to parent is issued.
  • When the parent has no default/no-arg constructors, that means it has explicit constructors and all of them requires arguments –
    1. If the child does not explicitly invoke any of the existing parent constructors, then a compile time error is issued.
    2. If the child constructor explicitly calls any of the existing parent constructors then the program continues without any error.

Thank you. Let’s have this type of conversation again. Good night.

Sure. Anytime.

Good night to you too.

Advertisements