5.3 Chaining Constructors Using this() and super()
A basic understanding of constructors (§3.7, p. 109) is beneficent for the discussion in this section.
The this() Constructor Call
Constructors cannot be inherited or overridden. They can be overloaded, but only in the same class. Since a constructor always has the same name as the class, each parameter list must be different when defining more than one constructor for a class. In Example 5.5, the class Light has three overloaded constructors. In the constructor at (3), the this reference is used to access the fields shadowed by the parameters. In the main() method at (4), the appropriate constructor is invoked depending on the arguments in the constructor call, as illustrated by the program output.
Example 5.5 Constructor Overloading
// File: DemoConstructorCall.java
class Light {
// Fields:
private int noOfWatts; // wattage
private boolean indicator; // on or off
private String location; // placement
// Constructors:
Light() { // (1) No-argument constructor
noOfWatts = 0;
indicator = false;
location = “X”;
System.out.println(“Returning from no-argument constructor no. 1.”);
}
Light(int watts, boolean onOffState) { // (2)
noOfWatts = watts;
indicator = onOffState;
location = “X”;
System.out.println(“Returning from constructor no. 2.”);
}
Light(int noOfWatts, boolean indicator, String location) { // (3)
this.noOfWatts = noOfWatts;
this.indicator = indicator;
this.location = location;
System.out.println(“Returning from constructor no. 3.”);
}
}
//______________________________________________________________________________
public class DemoConstructorCall {
public static void main(String[] args) { // (4)
System.out.println(“Creating Light object no. 1.”);
Light light1 = new Light();
System.out.println(“Creating Light object no. 2.”);
Light light2 = new Light(250, true);
System.out.println(“Creating Light object no. 3.”);
Light light3 = new Light(250, true, “attic”);
}
}
Output from the program:
Creating Light object no. 1.
Returning from no-argument constructor no. 1.
Creating Light object no. 2.
Returning from constructor no. 2.
Creating Light object no. 3.
Returning from constructor no. 3.
Example 5.6 illustrates the use of the this() construct, which is used to implement local chaining of constructors in the class when an instance of the class is created. The first two constructors at (1) and (2) from Example 5.5 have been rewritten using the this() construct in Example 5.6 at (1) and (2), respectively. The this() construct can be regarded as being locally overloaded, since its parameters (and hence its signature) can vary, as shown in the body of the constructors at (1) and (2). The this() call invokes the local constructor with the corresponding parameter list. In the main() method at (4), the appropriate constructor is invoked depending on the arguments in the constructor call when each of the three Light objects are created. Calling the no-argument constructor at (1) to create a Light object results in the constructors at (2) and (3) being executed as well. This is confirmed by the output from the program. In this case, the output shows that the constructor at (3) completed first, followed by the constructor at (2), and finally by the no-argument constructor at (1) that was called first. Bearing in mind the definition of the constructors, the constructors are invoked in the reverse order; that is, invocation of the no-argument constructor immediately leads to invocation of the constructor at (2) by the call this(0, false), and its invocation leads to the constructor at (3) being called immediately by the call this(watt, ind, “X”), with the completion of the execution in the reverse order of their invocation. Similarly, calling the constructor at (2) to create an instance of the Light class results in the constructor at (3) being executed as well.
If the this() call is specified, it must occur as the first statement in a constructor. The this() call can be followed by any other relevant code. This restriction is due to Java’s handling of constructor invocation in the superclass when an object of the subclass is created. This mechanism is explained in the next subsection.
Example 5.6 The this() Constructor Call
// File: DemoThisCall.java
class Light {
// Fields:
private int noOfWatts;
private boolean indicator;
private String location;
// Constructors:
Light() { // (1) No-argument constructor
this(0, false);
System.out.println(“Returning from no-argument constructor no. 1.”);
}
Light(int watt, boolean ind) { // (2)
this(watt, ind, “X”);
System.out.println(“Returning from constructor no. 2.”);
}
Light(int noOfWatts, boolean indicator, String location) { // (3)
this.noOfWatts = noOfWatts;
this.indicator = indicator;
this.location = location;
System.out.println(“Returning from constructor no. 3.”);
}
}
//______________________________________________________________________________
public class DemoThisCall {
public static void main(String[] args) { // (4)
System.out.println(“Creating Light object no. 1.”);
Light light1 = new Light(); // (5)
System.out.println(“Creating Light object no. 2.”);
Light light2 = new Light(250, true); // (6)
System.out.println(“Creating Light object no. 3.”);
Light light3 = new Light(250, true, “attic”); // (7)
}
}
Output from the program:
Creating Light object no. 1.
Returning from constructor no. 3.
Returning from constructor no. 2.
Returning from no-argument constructor no. 1.
Creating Light object no. 2.
Returning from constructor no. 3.
Returning from constructor no. 2.
Creating Light object no. 3.
Returning from constructor no. 3.