Skip to main content

Unit 3 · Topic 3.4

3.4 Constructors

A constructor gives a brand-new object its starting state. This topic covers what an object's state is, how to write constructors that set every instance variable, what Java does when you write no constructor, and why a constructor should copy a mutable object it's given.

Key terms

  • constructor
  • state
  • has-a relationship
  • default constructor
  • default values

State and has-a

An object's state is its attributes and their current values, stored in its instance variables. A Player object has-a name and has-a level. That's called a has-a relationship between the object and its data.

Writing constructors

A constructor has the same name as the class and no return type. When you call it with new, Java sets aside memory for the object, runs the constructor's body, and gives back a reference to the new object.

The constructor's job is to give every instance variable a starting value, usually from its parameters. Some instance variables don't come from a parameter at all. A counter of purchases starts at 0 and a score history might start empty, so the constructor sets those to fixed starting values. Constructor parameters need their own names, which can't be used outside the constructor. A class can have more than one constructor, as long as their parameter lists differ (overloading, from 1.13):

public class Player { private String name; private int level; public Player(String n, int startLevel) { name = n; level = startLevel; } public Player(String n) { name = n; level = 1; } public int getLevel() { return level; } }

new Player("Rae", 7) uses the first constructor. new Player("Jun") uses the second, which sets the level to 1 itself. Either way, every instance variable gets a value, so a.getLevel() is 7 and b.getLevel() is 1.

The default constructor

If you write no constructor at all, Java supplies one with no parameters, called the default constructor. It sets every instance variable to its default value:

TypeDefault value
int0
double0.0
booleanfalse
any reference type, such as Stringnull

Copy mutable objects you're given

A mutable object is one whose state can change after it's created, through methods like moveRight. If a constructor just stores the reference it was given, the new object and the caller share one object. Any later change the caller makes shows up inside your object too, which breaks encapsulation.

The fix is to store a copy: build a new object with the same data. Immutable objects like String are safe to share, because nobody can change them. Primitive parameters like an int or double don't need this, because the parameter is already a copy of the value.

Worked examples

Try each one yourself first, then open the solution.

  1. Example 1

    Default values

    Sensor has no constructor:public class Sensor { private int reading; private double average; private boolean active; private String label; public String report() { return reading + " " + average + " " + active + " " + label; } }What does this code print?Sensor s = new Sensor(); System.out.println(s.report());

    Show the solution
    1. Step 1: Since Sensor has no constructor, Java provides the default one, so new Sensor() compiles.
    2. Step 2: Every instance variable gets its default value: reading is 0, average is 0.0, active is false and label is null.
    3. Step 3: Joining null into a string with + gives the text null.

    Answer: It prints 0 0.0 false null.

  2. Example 2

    Sharing versus copying

    Point is a mutable class with a constructor Point(int startX, int startY), getters getX and getY, and a method moveRight(int dx) that adds dx to x. This version of Flag stores the point it's given:public class Flag { private Point spot; public Flag(Point p) { spot = p; } public int getSpotX() { return spot.getX(); } }What does this code print, and how should the constructor be fixed?Point home = new Point(2, 5); Flag f = new Flag(home); home.moveRight(10); System.out.println(f.getSpotX());

    Show the solution
    1. Step 1: home refers to a Point at (2, 5).
    2. Step 2: The constructor runs spot = p;, which copies the reference, not the object. Now home and the flag's spot refer to the same Point.
    3. Step 3: home.moveRight(10) moves that shared point to x = 12, so the flag's spot moves too. It prints 12, even though nobody changed the flag.
    4. Step 4: The fix is to store a copy in the constructor:
    5. Step 5: public class Flag { private Point spot; public Flag(Point p) { spot = new Point(p.getX(), p.getY()); } public int getSpotX() { return spot.getX(); } }
    6. Step 6: With this version, the flag has its own point at (2, 5), and the code prints 2.

    Answer: It prints 12. The constructor should store new Point(p.getX(), p.getY()) so later changes to home don't affect the flag; then it prints 2.

Common mistakes

  • Forgetting to set an instance variable in the constructor, so it's left at 0, false or null.
  • Writing void in front of a constructor. Then it's a method, not a constructor.
  • Storing a reference to a mutable object that was passed in, instead of a copy.
  • Expecting new Sensor() to work when the class has a constructor with parameters. Java only supplies the default constructor when you write none.

On the exam

  • On free-response Question 2, the constructor point usually depends on initializing every instance variable correctly, including ones that aren't parameters, like a counter that starts at 0.
  • Expect multiple-choice questions on default values and on which constructor calls compile.

Connected topics

Videos

Check yourself

4 questions on 3.4 Constructors. Pick an answer to see if you got it, and why.

Question 1 of 4

Consider the following class.public class Thing { private int count; private double rate; private boolean active; private String label; public int getCount() { return count; } public double getRate() { return rate; } public boolean isActive() { return active; } public String getLabel() { return label; } }What is printed as a result of executing the following code segment, which appears in a class other than the one shown?Thing t = new Thing(); System.out.println(t.getCount() + " " + t.getRate() + " " + t.isActive() + " " + t.getLabel());

Question 2 of 4

Consider the following incomplete class.public class Rectangle { private int width; private int height; public Rectangle(int w, int h) { /* missing code */ } public int getWidth() { return width; } public int getHeight() { return height; } }Which of the following can replace /* missing code */ so that new Rectangle(3, 8) makes a rectangle 3 wide and 8 high?

Question 3 of 4

A programmer writes a class Lamp with two private instance variables, int brightness and boolean on, and doesn't write any constructor. Which of the following is true?

Question 4 of 4

A Car class has the instance variables private Engine motor; and private int miles;. Which of the following best describes the relationship between a Car object and its Engine?

0 of 4 answered