6.3 Constructors


In creating objects of the type Fraction, we have been using statements that have a form like the following.
Fraction f = new Fraction(); 

The parentheses in the expression Fraction() make it look like a method call and, in fact, it is. The method is called a constructor method. We did not create such a method but, for every class, Java automatically creates a default constructor method that has the same identifier as the class. Constructor methods are instance methods used to initialize objects at the "tIme the objects are created.-The default method initializes any numeric fields to zero, boolean fields to false, and reference fields to the value null. We can, however, write our own constructors that do whatever initialization we wish. As an example, we can use a constructor to initialize objects of type Fraction as follows:

Example 1

Suppose, in the class Fraction, we created the following constructor:

public Fraction (int n, int d)
{
   num = n;
   den = d;
} 

Then, in our main method, say, we could write
Fraction f = new Fraction(2,3); 
This would declare f to be of type Fraction, create an object of type Fraction, set f to refer to that object, and initialize the object to represent the fraction 2/3.

There are a number of things about constructors that the example displays.
  1. The identifier of the constructor method is exactly the same as the identifier of the class; both are called Fraction.

  2. Unlike every method that we have seen so far, the constructor method does not specify a return type (not even VOid). It is implicit that the method returns an object of type Fraction.

  3. The constructor is an instance method. Thus, it can refer to the instance fields of the class (num and den), just as any other instance method can.

  4. The call to the constructor method differs from other calls to instance methods in that it does not use the dot notation. We wrote f = new Fraction(2,3); rather than new f.Fraction(2,3);

  5. The parameters to the constructor method were called n and d so that their identifiers did not conflict with num and den, the identifiers of the object that is implicitly associated with the method. If we had wanted to use num and den as identifiers of the explicit parameters, we could have written the definition as follows:

    public Fraction (int num, int den)
    {
       this.num num;
       this.den den;
    } 

    As usual, this means the current implicit object. The identifiers on the left side of the assignment statements refer to the this object's num and den fields while the identifiers on the right side refer to the explicit parameters to the method.

Java does not restrict us to having only one constructor method for a class. Like any other methods, constructors can be overloaded with each version having its own signature and each doing some different kind of initialization.

Example 2

The following constructor for the Fraction class could be used to create a Fraction object that has the same values as an existing Fraction object.

public Fraction (Fraction f)
{
   num f .num;
   den f.den;
} 

We can even replace the default constructor with one that does the kind of initialization that we want. For our Fraction class, the default constructor will, given the call
Fraction f = new Fraction(); 
assign both the num and den fields the value zero, so that the resulting object represents the indeterminate fraction 0/0. If we wanted to, we could replace this by a constructor that creates a fraction that represents 1/0.

Example 3

A constructor that initializes Fraction objects to represent 0/1 would take the following form:

public Fraction()
{
   num = 0;
   den = 1;
} 

This constructor could be invoked by the call
Fraction f = new Fraction(); 
just as the default constructor is called.


To show how these methods could be used, consider the following fragment:

Fraction p = new Fraction(3,5);
Fraction q = new Fraction(p);
Fraction r = new Fraction(); 

The first statement uses our first constructor to create an object representing the fraction 3/5. The second statement creates another object that also represents the fraction 3/5. The third statement creates an object that represents the fraction 0/1. The diagram illustrates the results.


We said, at the start of this section, that Java supplies a default constructor if we do not write our own. However, if we do create our own constructor(s), the default no longer operates. In such a situation, if we want to have a constructor that has no parameters and does only basic initialization, we must write it ourselves.

Example 4

The constructor

public Fraction ()
{
   num = den = 0;
} 

performs the actions of the default constructor for the Fraction class.
If a class has multiple constructors, it is sometimes possible to use the code from one constructor in another. The next example illustrates this idea.

Example 5

Suppose that a Student class has fields for a name, student number, and number of credits. Normally, a new student will not have any credits. The constructor for such a student might take the form

public Student (String n, String sn)
{
   name = n;
   studentNumber = sn;
   credits = 0;
} 

Sometimes a new student will already have some credits from another school. To handle such cases, we could write another constructor.

public Student (String n, String sn, int c)
{
   name = n;
   studentNumber = sn;
   credits = c;
} 

Notice that the two constructors have two lines of code that are identical. It is usually a good idea to avoid such repetition of multiple lines of code because, if a mistake is found or if the program is being modified at a later time, then the code must be changed in more than one place. We can avoid such repetition here by rewriting the first constructor as follows.

public Student (String n, String sn)
{
   this(n,sn,O);
} 

In Example 5, we have used this in a new way, as a reference to the constructor of the current implicit object. If a constructor contains a call to another constructor, that call must be the first statement of the constructor.

Exercise 6.3

    1. Extend the definition of the Fraction class that we have been developing to include the constructors discussed in this section.
    2. Write a main method that first constructs two Fraction objects representing the fractions 5/7 and 3/8 and then creates two other Fraction objects whose values are the sum and product of the original fractions. The method should produce no output; we will deal with printing of objects shortly. Use the methods plus and times from Section 6.2 in your method.

  1. For the class Circle defined as follows
    class Circle
    {
       double x; // x-coordinate of centre
       double y; // y-coordinate of centre
       double r; // radius
    } 
    1. Write a constructor method that has no parameters. The method should construct a Circle object with centre (0,0) and radius l.
    2. Write a constructor method that has three parameters representing the coordinates of the centre and the radius of the object to be constructed.
    3. Write a constructor method with a parameter, an object of type Circle. The method should construct a new Circle object with the same field values as those of the parameter.