4.4 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.

A constructor has the following general syntax:


<accessibility modifier> <class name> (<formal parameter list>)
            <throws clause> // Constructor header
  { // Constructor body
    <local variable declarations>
    <nested local class 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. Accessibility modifiers for constructors are discussed in Section 4.7 on page 131.

  • Constructors cannot return a value and, hence, cannot specify a return type, not even void, in the constructor header, but they can contain the simple form of the return statement in the constructor body.

  • 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 4.5, where a method declared at (2) has the same name as the constructor declared at (1). However, using such naming schemes is strongly discouraged.

Example 4.5 Namespaces
public class Name {

    Name() {                    // (1)
        System.out.println("Constructor");
    }

    void Name() {               // (2)
        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

Default Constructor

A default constructor is a constructor without any parameters. In other words, it has the following signature:


<class name>()

If a class does not specify any constructors, then an implicit default constructor is supplied for the class. The implicit default constructor is equivalent to the following implementation:


<class name>() { super(); } // No parameters. Calls superclass constructor.

The only action taken by the implicit default constructor is to call the superclass constructor. This ensures that the inherited state of the object is initialized properly (see Section 6.3, p. 243). In addition, all instance variables in the object are set to the default value of their type.

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 of implicit default constructor.
}

In the previous code, the following implicit default constructor is employed when a Light object is created at (1):

Light() { super(); }

Creating an object using the new operator with the implicit default constructor, as at (1), will initialize the fields of the object to their default values (i.e., 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 an implementation of the default constructor. In the following example, the class Light provides an explicit default constructor at (1). Note that it has the same name as the class, and that it does not take any parameters.

class Light {
    // ...
    // Explicit Default Constructor
    Light() {                        // (1)
        noOfWatts = 50;
        indicator = true;
        location  = "X";
    }
    //...
}

class Greenhouse {
    // ...
    Light extraLight = new Light();   // (2) Call of explicit default constructor.
}

The explicit default constructor ensures that any object created with the 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 explicit constructors, it can no longer rely on the implicit default constructor to set the state of the objects. If such a class requires a default constructor, its implementation must be provided. In the example below, class Light only provides a non-default constructor at (1). It is called at (2) when an object of 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-default 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 also 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 both an explicit implementation of the default constructor at (1) and a non-default constructor at (2). The constructors are overloaded, as is evident by their signatures. The non-default constructor is called when an object of class Light is created at (3), and the default constructor is likewise called at (4). Overloading of constructors allows appropriate initialization of objects on creation, depending on the constructor invoked (see also chaining of constructors in Section 6.3, p. 243.)

class Light {
    // ...
    // Explicit Default Constructor
    Light() {                                                  // (1)
        noOfWatts = 50;
        indicator = true;
        location  = "X";
    }

    // Non-default 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.
}