Section 3.3. Constructor Methods


[Page 111]

3.3. Constructor Methods

In the preceding section, we looked at several examples of mutator methods that change the values of private instance variables of an object. It is possible to define mutator methods to set the initial values of instance variables after an object is created, but initial values can also be set by constructors.

As you will recall from Chapter 0, a constructor method is used to create an instance (or object) of a class and to assign initial values to instance variables. A constructor declaration looks just like a method definition except that it must have the same name as the class, and it cannot declare a result type. Unlike the class-level variables and methods of a class, constructors are not considered members of the class. Therefore, they are not inherited by a class's subclasses. Access to constructors is governed by the access modifiers public and private. Here is a simple constructor for our OneRowNim class:

public OneRowNim() {   nSticks = 7;     player = 1; } 


Constructor names


This constructor merely sets the initial values of the instance variables, nSticks and player. In our current version of OneRowNim, these variables are given initial values by using initializer statements when they are first declared:

private int nSticks = 7; private int player = 1; 


Constructing an object


So we now have two ways to initialize a class's instance variables. In the OneRowNim class it doesn't really matter which way we do it. However, the constructor provides more flexibility because it allows the state of the object to be initialized at runtime. Of course, it would be somewhat redundant (though permissible) to initialize the same variable twice, once when it is declared and again in the constructor, so we should choose one or the other way to do this. For now, let's stick with initializing the instance variables when they are declared.

Initializing variables


Effective Design: Constructors

Constructors provide a flexible way to initialize an object's instance variables when the object is created.


A constructor cannot return a value, and therefore its declaration cannot include a return type. Because they cannot return values, constructors cannot be invoked by a regular method invocation. Instead, constructors are invoked as part of an instance creation expression when instance objects are created. An instance creation expression involves the keyword new followed by the constructor invocation:

OneRowNim game1            // Declare     = new OneRowNim();     // and instantiate game1 OneRowNim game2            // Declare     = new OneRowNim();     // and instantiate game2 


Constructors can't return a value



[Page 112]

Note here that we have combined variable declaration and instantiation into a single statement, whereas in some previous examples we used separate declaration and instantiation statements. Either way is acceptable.

Java Language Rule: Constructors

Constructors cannot return a value. Therefore, no return type should be declared when a constructor is defined.


Debugging Tip: When to Use Return

All method definitions except constructors must declare a return type.


Constructors should be used to perform the necessary initialization operations during object creation. In the case of a OneRowNim object, what initializations could be performed? One initialization that would seem appropriate is to initialize the initial number of sticks to a specified number. In order to do this, we would need a constructor with a single int parameter:

public OneRowNim(int sticks) {   nSticks = sticks; } 


State initialization


Now that we have this constructor, we can use it when we create instances of OneRowNim:

OneRowNim game1 = new OneRowNim(21); OneRowNim game2 = new OneRowNim(13); 


The effect of these statements is the same as if we had used the setSticks() method that was discussed briefly on page 105. The difference is that we can now set the number of sticks when we create the object.

Should we keep the preceding constructor, the setSticks() method, or both in our class definition? The constructor can only be invoked as part of a new statement when the object is created, but the setSticks() method could be called anytime we want. In many cases, having redundant methods for doing the same task in different ways would be an asset, because it allows for more flexibility in how the class can be used. However, for a game like One-Row Nim, a major concern is that the two instance variables get changed only in a manner consistent with the rules for One-Row Nim. The best way to guarantee this is to have takeSticks() as the only method that changes the instance variables nSticks and player. The only time it should be possible to set the number of sticks for a game is when a constructor is used to create a new instance of OneRowNim.

Self-Study Exercises

Exercise 3.5

What's wrong with the following constructor definition?

public void OneRowNim(int sticks) {   nSticks = sticks; } 


Exercise 3.6

Change the OneRowNim(int sticks) constructor so that it sets the number of sticks, and also have it also set player 2 as the player who takes the first turn.


[Page 113]

3.3.1. Default Constructors

As we noted in Chapter 2, Java automatically provides a default constructor when a class does not contain a constructor.

Java Language Rule: Default Constructor

If a class contains no constructor declarations, Java will automatically supply a default constructor. The default constructor takes no parameters. If the class is public, the default constructor will also be public and, thus, accessible to other objects.


The default constructor's role is simply to create an instance (an object) of that class. It takes no parameters. In terms of what it does, the default constructor for OneRowNim would be equivalent to a public constructor method with an empty body:

public OneRowNim() { } 


This explains why the following statement was valid when a class definition of OneRowNim contained no explicit definition of a constructor:

OneRowNim game = new OneRowNim(); 


3.3.2. Constructor Overloading and Method Signatures

It is often quite useful to have more than one constructor for a given class. For example, consider the following two OneRowNim constructors:

public OneRowNim() {} // Constructor #1 public OneRowNim(int sticks)   // Constructor #2 {   nSticks = sticks; } 


Flexible design


The first is an explicit representation of the default constructor. The second is the constructor we defined earlier to initialize the number of sticks in a OneRowNim object. Having multiple constructors lends flexibility to the design of a class. In this case, the first constructor merely accepts OneRowNim's default initial state. The second enables the user to initialize the number of sticks to something other than the default value.

In Java, as in some other programming languages, when two different methods have the same name, it is known as method overloading. In this case, OneRowNim is used as the name for two different constructor methods. What distinguishes one constructor from another is its signature, which consists of its name together with the number and types of formal parameters it takes. Thus, our OneRowNim constructors have the following signatures:

OneRowNim() OneRowNim(int) 


Method overloading



[Page 114]

Both have the same name, but the first takes no parameters, whereas the second takes a single int parameter.

The same point applies to methods in general. Two methods can have the same name as long as they have distinct signatures. A method signature consists of its name, and the number, types, and order of its formal parameters. A class may not contain two methods with the same signature, but it may contain several methods with the same name, provided each has a distinct signature.

Methods are known by their signatures


Java Language Rule: Method Signature

A method signature consists of the method's name, plus the number, types, and order of its formal parameters. A class may not contain two methods with the same signature.


There is no limit to the amount of overloading that can be done in designing constructors and methods. The only restriction is that each method have a distinct signature. For example, suppose that in addition to the two constructors we have already defined, we want a constructor that would let us set both the number of sticks and the player who starts first. The following constructor will do what we want:

public OneRowNim(int sticks, int starter) {   nSticks = sticks;   // Set the number of sticks     player = starter;   // Set who starts } 


When calling this constructor, we would have to take care to pass the number of sticks as the value of the first argument and either 1 or 2 as the value of the second argument:

OneRowNim game3 = new OneRowNim(14, 2); OneRowNim game4 = new OneRowNim(31, 1); 


If we mistakenly reversed 14 and 2 in the first of these statements, we would end up with a OneRowNim game that starts with two sticks and has player 14 as the player with the first move.

We have now defined three constructor methods for the OneRowNim class. Each constructor has the name OneRowNim, but each has a distinct signature:

OneRowNim() OneRowNim(int) OneRowNim(int, int) 



[Page 115]

3.3.3. Constructor Invocation

A constructor method is invoked only as part of a new expression when an instance object is first created. Each of these is a valid invocation of a OneRowNim constructor:

OneRowNim game1 = new OneRowNim();        // Default constructor OneRowNim game2 = new OneRowNim(21);      // Sets number of sticks OneRowNim game3 = new OneRowNim(19, 2);   // Sets both instance variables 


A constructor is invoked once to create an object


The following constructor invocations are invalid because there are no matching constructor definitions:

OneRowNim game4 = new OneRowNim("21");      // No matching constructors OneRowNim game5 = new OneRowNim(12, 2, 5); 


In the first case, there is no constructor method that takes a String parameter, so there is no matching constructor. In the second case, there is no constructor that takes three int arguments. In both cases, the Java compiler would complain that there is no constructor method that matches the invocation.

Debugging Tip: Method Call

The signature of the method callits name and the number, types, and order of its argumentsmust exactly match the signature of the method definition.





Java, Java, Java(c) Object-Orienting Problem Solving
Java, Java, Java, Object-Oriented Problem Solving (3rd Edition)
ISBN: 0131474340
EAN: 2147483647
Year: 2005
Pages: 275

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net