AP® Computer Science A review sheet from Aim for Five (aimforfive.com/csa/units/3/3-4)
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:
| Type | Default value |
|---|---|
| int | 0 |
| double | 0.0 |
| boolean | false |
| any reference type, such as String | null |
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.
- Example 1
Default values
Sensorhas 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 solutionHide the solution
- Step 1: Since
Sensorhas no constructor, Java provides the default one, sonew Sensor()compiles. - Step 2: Every instance variable gets its default value:
readingis 0,averageis 0.0,activeisfalseandlabelisnull. - Step 3: Joining
nullinto a string with+gives the textnull.
Answer: It prints
0 0.0 false null. - Step 1: Since
- Example 2
Sharing versus copying
Pointis a mutable class with a constructorPoint(int startX, int startY), gettersgetXandgetY, and a methodmoveRight(int dx)that addsdxto x. This version ofFlagstores 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 solutionHide the solution
- Step 1:
homerefers to aPointat (2, 5). - Step 2: The constructor runs
spot = p;, which copies the reference, not the object. Nowhomeand the flag'sspotrefer to the samePoint. - 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. - Step 4: The fix is to store a copy in the constructor:
- 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(); } } - 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 storenew Point(p.getX(), p.getY())so later changes tohomedon't affect the flag; then it prints 2. - Step 1:
Common mistakes
- Forgetting to set an instance variable in the constructor, so it's left at
0,falseornull. - Writing
voidin 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.
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());
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?
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?
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