3.3 Constructors
The main purpose of constructors is to set the initial state of an object, when the object is created by using the new operator.
For the purpose of this book, we will use the following simplified syntax of a constructor:
accessibility_modifier class_name (formal_parameter_list) throws_clause // Constructor header { // Constructor body local_variable_declarations statements }
Constructor declarations are very much like method declarations. However, the following restrictions on constructors should be noted:
Modifiers other than an accessibility modifier are not permitted in the constructor header. For accessibility modifiers for constructors, see §4.7, p. 123.
Constructors cannot return a value and, therefore, do not specify a return type, not even void, in the constructor header. But their declaration can use the return statement that does not return a value in the constructor body (§6.4, p. 224).
The constructor name must be the same as the class name.
Class names and method names exist in different namespaces. Thus, there are no name conflicts in Example 3.2, where a method declared at (2) has the same name as the constructor declared at (1). A method must always specify a return type, whereas a constructor does not. However, using such naming schemes is strongly discouraged.
A constructor that has no parameters, like the one at (1) in Example 3.2, is called a no-argument constructor.
Example 3.2 Namespaces
public class Name { Name() { // (1) No-argument constructor System.out.println("Constructor"); } void Name() { // (2) Instance method System.out.println("Method"); } public static void main(String[] args) { new Name().Name(); // (3) Constructor call followed by method call } }
Output from the program:
Constructor Method
The Default Constructor
If a class does not specify any constructors, then a default constructor is generated for the class by the compiler. The default constructor is equivalent to the following implementation:
class_name() { super(); } // No parameters. Calls superclass constructor.
A default constructor is a no-argument constructor. The only action taken by the default constructor is to call the superclass constructor. This ensures that the inherited state of the object is initialized properly (§7.5, p. 282). In addition, all instance variables in the object are set to the default value of their type, barring those that are initialized by an initialization expression in their declaration.
In the following code, the class Light does not specify any constructors:
class Light { // Fields: int noOfWatts; // Wattage boolean indicator; // On or off String location; // Placement // No constructors //... } class Greenhouse { // ... Light oneLight = new Light(); // (1) Call to default constructor }
In this code, the following default constructor is called when a Light object is created by the object creation expression at (1):
Light() { super(); }
Creating an object using the new operator with the default constructor, as at (1), will initialize the fields of the object to their default values (that is, the fields noOfWatts, indicator, and location in a Light object will be initialized to 0, false, and null, respectively).
A class can choose to provide its own constructors, rather than relying on the default constructor. In the following example, the class Light provides a no-argument constructor at (1).
class Light { // ... Light() { // (1) No-argument constructor noOfWatts = 50; indicator = true; location = "X"; } //... } class Greenhouse { // ... Light extraLight = new Light(); // (2) Call of explicit default constructor }
The no-argument constructor ensures that any object created with the object creation expression new Light(), as at (2), will have its fields noOfWatts, indicator, and location initialized to 50, true, and "X", respectively.
If a class defines any constructor, it can no longer rely on the default constructor to set the state of its objects. If such a class requires a no-argument constructor, it must provide its own implementation, as in the preceding example. In the next example the class Light does not provide a no-argument constructor, but rather includes a non-zero argument constructor at (1). It is called at (2) when an object of the class Light is created with the new operator. Any attempt to call the default constructor will be flagged as a compile-time error, as shown at (3).
class Light { // ... // Only non-zero argument constructor: Light(int noOfWatts, boolean indicator, String location) { // (1) this.noOfWatts = noOfWatts; this.indicator = indicator; this.location = location; } //... } class Greenhouse { // ... Light moreLight = new Light(100, true, "Greenhouse");// (2) OK Light firstLight = new Light(); // (3) Compile-time error }
Overloaded Constructors
Like methods, constructors can be overloaded. Since the constructors in a class all have the same name as the class, their signatures are differentiated by their parameter lists. In the following example, the class Light now provides explicit implementation of the no-argument constructor at (1) and that of a non-zero argument constructor at (2). The constructors are overloaded, as is evident by their signatures. The non-zero argument constructor at (2) is called when an object of the class Light is created at (3), and the no-argument constructor is likewise called at (4). Overloading of constructors allows appropriate initialization of objects on creation, depending on the constructor invoked (see chaining of constructors in §7.5, p. 282). It is recommended to use the @param tag in a Javadoc comment to document the formal parameters of a constructor.
class Light { // ... // No-argument constructor: Light() { // (1) noOfWatts = 50; indicator = true; location = "X"; } // Non-zero argument constructor: Light(int noOfWatts, boolean indicator, String location) { // (2) this.noOfWatts = noOfWatts; this.indicator = indicator; this.location = location; } //... } class Greenhouse { // ... Light moreLight = new Light(100, true, "Greenhouse"); // (3) OK Light firstLight = new Light(); // (4) OK }