Object Initialization and Constructors
A constructor has the same name as its class, has no return type, and initializes an object when it is created.
Predicting a Pair of Dice Before Reading
When a program creates an object, something has to set up that object's starting values. In Java, that job belongs to a constructor. This article works from one class, PairOfDice, which represents a pair of dice. The class has two instance variables, die1 and die2, and two methods that set them in different ways.
Before reading the explanation, commit to an answer. Suppose the code runs new PairOfDice(3, 5). Ask yourself which assignments run and what die1 and die2 hold immediately afterward. Write down your guess. Then keep reading to check it.
Reading the PairOfDice Class
The class below follows the behavior described in the source. Read it once from top to bottom and mark the two places where die1 and die2 get their values. There are three members in the class that run code: two constructors and one method called roll().
- die1 and die2 are the two instance variables the object stores.
- The no-argument constructor does not assign values itself. Its body is a single call to
roll(). - The two-argument constructor assigns the values it receives directly to die1 and die2.
roll()sets each die to a random number from 1 to 6.
Telling Constructors Apart from Methods
The name is the key identifying feature of a constructor. Both constructors in PairOfDice are named PairOfDice, exactly matching the class name. A constructor also has no return type. The method roll() differs on both points: it is declared void, which means it does its work without returning a value to the caller, and its name is not the class name.
| Feature | Constructor | Method roll() |
|---|---|---|
| Name | Matches the class name: PairOfDice | roll, which is not the class name |
| Return type | None | void |
| Purpose | Initializes the object when it is created | Sets die1 and die2 to random values when called |
| How it runs | Runs through new PairOfDice(...) | Runs when called by name, such as dice.roll() |
Distinguishing a constructor from a method in the PairOfDice class
Tracing the Two-Argument Constructor
Creating a pair of dice with known values
What are the values of die1 and die2 immediately after new PairOfDice(3, 5) runs?
- 1Select the constructor
The call passes two integers, so the two-parameter constructor
PairOfDice(int val1, int val2)is the one that runs. - 2Bind the arguments
Inside the constructor, val1 holds 3 and val2 holds 5.
- 3Assign die1
The statement die1 = val1 copies 3 into die1.
- 4Assign die2
The statement die2 = val2 copies 5 into die2.
die1 is 3 and die2 is 5. Because the constructor assigns the given values directly, the result is predictable every time.
What do you think happens?
After new PairOfDice(3, 5), what are die1 and die2?
Reveal answer
die1 is 3 and die2 is 5.
The two-argument constructor assigns its parameters directly to the instance variables, so the values come straight from the call.
Tracing the No-Argument Constructor
The no-argument constructor takes a different route. It does not assign die1 or die2 itself. Its body is one call, roll(), and roll() is the method that sets both dice. A constructor can therefore produce its result indirectly, by handing the work to another method of the same class.
PairOfDice dice = new PairOfDice(3, 5);Both values were supplied by the caller, so die1 is 3 and die2 is 5.
PairOfDice dice = new PairOfDice();The no-argument constructor calls roll(), so die1 and die2 each hold a random value from 1 to 6.
How Java Chooses Between Overloaded Constructors
PairOfDice defines two constructors with the same name and different parameter lists. This is called constructor overloading. It gives the class flexibility: a caller can create a pair of dice with random starting values by passing no arguments, or with specific known values by passing two integers. The arguments in the call are what select the constructor.
Read the flowchart as a decision about arguments. A call with two integers goes to the two-parameter constructor, whose values are predictable. A call with no arguments goes to the no-argument constructor, which hands off to roll(). The unexpected-looking result, a random value, first appears at the roll() step, not at the moment the object is created. That is the point to check when a dice object's values surprise you.
Mistakes Learners Make with Constructors
Common mistake Treating every method as a constructor because it appears near the top of the class
What it looks likeAssuming roll() initializes the object because it is declared right after the constructors.
Why it failsA constructor is identified by its name matching the class and by having no return type.
roll()is declared void and has a different name.Do this insteadCheck the name first. If it matches the class name and has no return type, it is a constructor.
Common mistake Assuming the no-argument constructor sets die1 and die2 directly
What it looks likePredicting that new PairOfDice() leaves both dice at the same fixed value.
Why it failsThe constructor body only calls
roll(), androll()assigns random values from 1 to 6.Do this insteadFollow the call into roll() to find where the values are actually set.
Common mistake Expecting the two-argument result to be random
What it looks likeThinking new PairOfDice(3, 5) might produce different numbers on each run.
Why it failsThe two-argument constructor assigns the values it receives directly, so the output is predictable.
Do this insteadUse the arguments in the call to predict the values, as long as the two-parameter constructor is selected.
Common mistake Choosing a constructor by the variable name instead of the arguments in the new expression
Finding the Point Where a Result Goes Unexpected
A program contains the line PairOfDice game = new PairOfDice(); and then prints game.die1 and game.die2. Without running the code, describe which constructor runs, which method sets the values, and what kind of values you should expect. Identify the exact line where the unpredictable result begins.
Hints
- Count the arguments in the new expression first.
- Look at the body of the constructor you selected. Does it assign values itself?
- The unpredictable value starts where the random numbers are generated, not where the object is created.
Key Takeaways
- A constructor has the same name as its class, has no return type, and initializes an object when it is created.
- A class can define several constructors with different parameter lists, and the arguments in the new expression select which one runs.
- The two-argument PairOfDice constructor assigns its values directly, so its results are predictable.
- The no-argument PairOfDice constructor calls
roll(), so its results are random values from 1 to 6, and the unexpected value first appears insideroll().