Java Constructor Chaining – Calling one constructor from another constructor is generally referred to as constructor chaining. This can be achieved in two ways.
- this()
- super()
in some cases we use only this(), in some other cases, we use only super(). Sometimes we use both (but not directly).
Normal Java constructor calling (without chaining)
When we create an object, its constructor is invoked and the code in that constructor is executed. By default, the default constructor (a constructor without arguments) is invoked when we create an object.
If we specify any arguments along with object creation, then the corresponding (argumented) constructor will be executed.
Example 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class Person { Person() //default constructor { } Person(int x) //an argumented constructor { } } class Chain { public static void main(String arg[]) { Person p1=new Person(); //default constructor is invoked Person p2=new Person(21); //argumented constructor is invoked } } |
Example 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
class Constructer { Constructer() { System.out.println("constructer with zero arguments"); } Constructer(int x) { System.out.println("constructer with argument one type int "+"("+x +")"); } Constructer(double x) { System.out.println("constructer with argument one type double"+"("+x +")"); } Constructer(int x,int y) { System.out.println("constructer with two arguments type int"+"("+x+","+y+")"); } Constructer(double x,double y) { System.out.println("constructer with two argument type double"+"("+x+","+y+")"); } Constructer(double x,int y) { System.out.println("constructer with two arguments type double and int "+"("+x+","+y+")"); } Constructer(int x,double y) { System.out.println("constructer with two arguments type int and double"+"("+x+","+y+")"); } Constructer(int x,int y,double z) { System.out.println("constructer with three arguments two of type int and one is double"+"("+x+","+y+","+z+")"); } } class ConstructerExample { public static void main(String args[]) { Constructer c1=new Constructer(); Constructer c2=new Constructer(1); Constructer c3=new Constructer(1.0); Constructer c4=new Constructer(2,3); Constructer c5=new Constructer(3.4,4.5); Constructer c6=new Constructer(1.2,2); Constructer c7=new Constructer(2,3.2); Constructer c8=new Constructer(1,2,3); } } |
Output:
1 2 3 4 5 6 7 8 |
constructer with zero arguments constructer with argument one type int (1) constructer with argument one type double(1.0) constructer with two arguments type int(2,3) constructer with two argument type double(3.4,4.5) constructer with two arguments type double and int (1.2,2) constructer with two arguments type int and double(2,3.2) constructer with three arguments two of type int and one is double(1,2,3.0) |
Constructor chaining with this()
Constructor calling (with chaining):
Suppose we want to call both the constructors (the default constructor and the argumented constructor) with an object creation, then we call one constructor from another constructor so that both will be executed.
This mechanism of invoking more than one constructor (one constructor calling another constructor) with a single object creation is known as constructor chaining.
The method this() is used to call one constructor from another constructor.
Example for this():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class Person { Person() { System.out.println("A"); } Person(int x) { this(); System.out.println("B"); } } class Chain { public static void main(String arg[]) { Person p2=new Person(21); } } |
Output:
1 2 |
A B |
In the above example, when an object is created, the control goes to the argumented constructor first (as the object is created with an int argument) and found this() as the first statement.
With this(), control goes to the default constructor and executes the code in that (prints A) and then comes back to execute the code in the argumented constructor (prints B).
More constructors involved in chaining
If we want to call the default constructor then this() is used without any arguments. If we want to call any argumented constructor then this() is used with corresponding arguments.
In the following example, we have 3 constructors involved in the chaining.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
class Person { Person() { this(10,20); System.out.println("A"); } Person(int x) { System.out.println("B"); } Person(int x,int y) { this(x); System.out.println("C"); } } class Chain { public static void main(String arg[]) { Person p2=new Person(); } } |
Output:
1 2 3 4 5 |
B C A |
In the above example, we are creating an object without arguments. So the default constructor is invoked first. From there (default constructor) the method this() is used with two arguments like “this(10,20)”.
- So the corresponding constructor (with 2 arguments) will be invoked and control goes there. In that constructor (2-args) again this() is used with one argument like “this(x)”.
- So the control goes to the 1-argumented constructor of the class to print B. From there it will come back to 2-args constructor to print C. from there it will come back to default constructor to print A.
Recursive constructor invocation is not allowed
We can call any number of constructors in this way. But an already invoked constructor should not be called again in the sequence. It means recursion is not allowed in constructor chaining. so the following code is invalid.
Example:
1 2 3 4 5 6 7 8 9 10 |
Person() { this(10); System.out.println("A"); } Person(int x) { this(); System.out.println("B"); } |
The this() should be the first statement in a constructor if it exists. We cannot write this() after any statement. So the following code is invalid.
Example:
1 2 3 4 5 |
Person() { System.out.println("A"); this(10); //not allowed } |
Constructor Chaining with super()
We can call a constructor of the current class only with this(). When inheritance is involved, and a child class object is created, an object of the parent class is also created as part of the child class object.
- As parent object is created (along with child object) its constructor should also be invoked. In this case also, by default, the default constructor of the parent class is invoked with child class constructor.
- If we want any argumented constructor of the parent class to be called with a child class constructor then we can exclusively invoke that using super().
- Using super() without arguments will call the default constructor of the parent class.
- To call (invoke) any argumented constructor of the parent class we should invoke super() with corresponding arguments.
Note: when a child class object is created, even though the control comes to child class constructor first, it will not execute the code in child class constructor.
From child class constructor it will go to the parent class constructor and executes it. then only it comes back to execute the child class constructor. So the parent class constructor is executed before the child class constructor.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
class Person { Person() { System.out.print("A"); } Person(int x) { System.out.print("B"); } Person(int x,int y) // this method is not invoked in this program { System.out.print("C"); } } class Emp extends Person { Emp() { //by default the default constructor of Person is invoked System.out.print("X"); } Emp(int x) { super(); // default constructor of Person is invoked System.out.print("Y"); } Emp(int x,int y) { super(x); //1-argumented constructor of Person is invoked System.out.print("Z"); } } class Chain { public static void main(String arg[]) { Emp e1=new Emp(); Emp e2=new Emp(10); Emp e3=new Emp(20,30); } } |
Output:
1 |
AXAYBZ |
In the above example, we have created 3 objects of Emp (child class). For each object creation, a parent class constructor and a child class constructor are invoked.
For the first statement, “new Emp()”, control goes to default constructor of child class (Emp) and there is no specification of which version of the parent class constructor to call.
So the default constructor of the parent class (Person) is invoked. After executing the parent class constructor the control comes back to execute the actual code of child class constructor. This part prints AX.
- For the second statement, “new Emp(10)”, control goes to the 1-argumented constructor of Emp and found super() without arguments there.
- So in this case also the default constructor of Person is executed and then, after coming back, the code in Emp(int) is executed. This part prints AY.
- For the third statement, “new Emp(20,30)”, control goes to the 2-argumented constructor of Emp and found super(x). so it will go to the 1-argumented constructor of Person.
Hence code in Person(int) is executed and then, after coming back, the code in Emp(int, int) is executed. This part prints BZ.
More chaining with super():
Suppose three classes are involved (say A, B and C where A is a parent to B and B is a parent to C) and third class (C) object is created, then control goes to the constructor of C
But before executing the statements in that it goes to the constructor of B. Even in B, before executing statements of B, it goes to the constructor of A.
After executing the code in A constructor, the control comes back to execute the code in B’s constructor. Once that execution is over, the control comes to execute code in C.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
class A { A() { System.out.print("A"); } } class B extends A { B() { System.out.print("B"); } } class C extends B { C() { System.out.print("C"); } } class Chain { public static void main(String arg[]) { new C(); } } |
Output:
1 |
ABC |
super() should be the first statement
similar to this(), the super() should also be the first statement in a constructor, if it exists. So the following code is invalid.
Example:
1 2 3 4 5 |
A() { System.out.print("A"); super(); //invalid } |
A constructor cannot have both this() and super() at the same time
As this() and super() should be the first statement(s) in a constructor we cannot use them in a single constructor at a time. So this following code will not be executed.
Example:
1 2 3 4 5 6 |
B(int x) { super(); this(); //not allowed System.out.print("this is super"); } |
this() and super() both involved:
Even though the system does not allow this() and super() together used in a single constructor, then can be used in constructor chaining so that they get executed accordingly.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
class A { A() { System.out.print("A0"); } A(int x) { this(); System.out.print("A1"); } } class B extends A { B() { super(10); System.out.print("B0"); } B(int x) { this(); System.out.print("B1"); } } class Chain { public static void main(String arg[]) { new B(20); } } |
Output:
1 |
A0A1B0B1 |
In the above example, first control goes to the argumented constructor of B and from there it will go to default constructor of B (with this()). From there, it will go to the argumented constructor of A (with super(10)).
From there it will move to default constructor of A (with this()). From there the printing takes place in chaining.
Note: if we have a constructor without a super() or this(), then the system automatically assumes super() as existing. So the following two codes are the same.
Example 1:
1 2 3 4 5 6 7 |
class Sub extends Sup { Sub() { System.out.print("child"); } } |
Example 2:
1 2 3 4 5 6 7 8 |
class Sub extends Sup { Sub() { super(); System.out.print("child"); } } |