Primitive values are simple — a box holds the value directly. Objects are richer: a class is a blueprint, and an object is one thing built from that blueprint. The variable does not hold the object itself; it holds a reference (think: an arrow) to where the object lives.
Primitive vs. reference
An int variable stores its number. An object variable stores a reference to an object stored elsewhere in memory. Two variables can point at the same object.
[Diagram — see the figure in the print workbook.]
Building an object with new
The keyword new builds an object by calling a constructor — a special method with the same name as the class. The constructor's parameters tell you what information the object needs.
// Given this constructor header from the documentation:
// public BankAccount(String owner, double balance)
BankAccount account = new BankAccount("Asha", 50.0);
Reading a constructor header tells you exactly what to pass: here, a String then a double, in that order.
No-argument constructors
Some classes provide a constructor that takes no information. You still need the empty parentheses.
Random rng = new Random(); // from java.util.Random
String empty = new String(); // an empty String
null and the NullPointerException
A reference variable can hold null, meaning “points at nothing.” Calling a method on null crashes the program with a NullPointerException at run time.
Worked example 1
Create an object with a no-argument constructor.
Random rng = new Random();
int roll = rng.nextInt(6) + 1; // 1..6
new Random() builds a random-number generator. We then call a method on it. (We cover nextInt patterns in Lesson 1.6.)
Worked example 2
Read a constructor header and call it.
Rectangle r = new Rectangle(4, 6);
Suppose the documentation lists: public Rectangle(int width, int height). Create a 4-by-6 rectangle.
The header says the order is width then height, both int. So we pass 4, 6 in that order.
Worked example 3
What does a reference variable actually store?
After String s = new String("hi");, what is in the box named s?
Not the text “hi” itself, but a reference to a String object that contains “hi”. The object lives elsewhere; s just points to it.
Worked example 4
Aliasing: two names, one object.
Given an object with a mutable balance, after BankAccount b = account; you call b.deposit(10). What is account's balance?
It also increased by 10. b and account are two arrows to the same object, so a change through either is seen by both.
Worked example 5
Spot the run-time crash.
String name = null;
System.out.println(name.length());
name points at nothing, so calling .length() on it throws a NullPointerException. The line compiles fine — the error happens when the program runs.
Common trap: Assigning references does not copy the object
BankAccount b = account; does not make a second account. It makes b a second arrow to the same object. A change made through one variable is visible through the other — they are aliases.
Hack: new builds, = relabels
Only new creates an object. A plain = between two object variables just copies the arrow. When a question shows two reference variables and then changes the object, ask: “Are these two arrows pointing at the same object?” If yes, a change through one is seen through the other.
To read any constructor or method on the exam, read its header left to right: the name, then the parameter types in order. The header is a recipe for what to pass.