Multiple Constructors
You may have noticed that you have not added constructors to all your classes. If you omit constructors from your class, Java automatically generates a no arguments constructor for you: this is called the default constructor. The default constructor does not do anything, but it is the reason why you can instantiate a class with no constructors, for instance:
A a = new A();
As soon as you add your own constructor to a class, or extend a class that has a constructor defined, the default constructor disappears and can no longer be invoked. Java assumes that because you have added a constructor you want all code to use this constructor.
It is, however, possible to add a no arguments constructor alongside another constructor: the following class has two constructors:
package constructors;
public class Person {
private String firstName;
private String lastName;
public Person() {}
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
In fact, a class can have as many constructors as you need, as long as each constructor is unique in terms of the number and/or type of parameters.
I will now create a slightly more complex example. I want to add a yearRegistered field to the Person class. This needs to be populated with the current year when a Person is instantiated, and can never be changed after that point.
In order to create a field that can never be changed I can mark it as final. As mentioned earlier in the book, a final field can only be initialized on the line that declares it, or inside a constructor.
Inside this program I want to initialize the field from a Calendar so that it is always assigned the current year. This introduces a problem, however, because I don’t want to add the same code to both constructors. I can overcome this problem as follows:
package constructors;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class Person {
private String firstName;
private String lastName;
private final int yearRegistered;
public Person() {
Calendar c = new GregorianCalendar();
yearRegistered = c.get(Calendar.YEAR);
}
public Person(String firstName, String lastName) {
this();
this.firstName = firstName;
this.lastName = lastName;
}
}
This example takes advantage of the GregorianCalendar class. This will be examined in detail later in the book, along with a better way of encapsulating years.
I have placed the code for initializing yearRegistered in the no-arguments constructor. I then invoke the no-arguments constructor from the second constructor by calling this(). The call to this() must be the first line in the constructor, and ensures that the code in the no-arguments constructor is executed regardless of which constructor is invoked.
This is a very common pattern with constructors, and can include several levels of invocation. For instance, a three arguments constructor may invoke a two arguments constructor, which in turn invokes a no arguments constructor. The only thing you need to guard against is creating a loop – for instance if the no-arguments constructor invoked the three arguments constructor.
If you ever find yourself writing the same code in multiple constructors, think back to this example and try to structure your code to remove the duplication.