Object References and Null
A TV remote isn't the TV. Two remotes can control the same TV: press volume up on either and the same TV gets louder. A remote with no TV paired to it controls nothing at all. In Java, a variable of a class type is a remote, not the object: it holds a reference to an object on the heap. Understanding this one idea explains aliasing, null, NullPointerException and garbage collection.
Two References, One Object
public class Refs {
static class Wallet {
int balance;
}
public static void main(String[] args) {
Wallet a = new Wallet();
a.balance = 500;
Wallet b = a;
b.balance = 800;
System.out.println("a.balance = " + a.balance);
System.out.println("same object? " + (a == b));
}
}a.balance = 800
same object? trueHow it works
- Line 7 creates one
Walletobject and stores a reference to it ina. - Line 9:
b = acopies the reference, not the object. Now two variables point to one wallet. This is called aliasing. - Line 10 changes the wallet through
b, so reading it throughashows 800. a == bcompares references:true, the same object.
Try it yourself: replace line 9 with Wallet b = new Wallet();. What does line 11 print now?
null: A Reference to Nothing
A reference variable can hold null, meaning "no object". Calling a method or reading a field through null throws a NullPointerException (NPE):
Wallet c = null;
System.out.println(c == null); // true
c.balance = 1; // NullPointerExceptionException in thread "main" java.lang.NullPointerException: Cannot assign field "balance" because "c" is nullSince Java 14, the message says exactly what was null. If the class was compiled without debugging information, you see "<local3>" instead of "c"; compiling with javac -g (or using an IDE) gives the variable name.
Comparing References
| Expression | Asks |
|---|---|
a == b | Do a and b refer to the same object? |
a.equals(b) | Are the two objects equal in value? (as defined by the class; see "Object Equality and Hash Codes in Java") |
a == null | Does a refer to no object? |
When Objects Become Garbage
An object stays alive as long as some reference can reach it. When the last reference is gone (set to null, reassigned, or the variable goes out of scope), the object is unreachable, and the garbage collector can free its memory. You never delete objects yourself in Java. A later lesson shows how the garbage collector decides.
public class Reach {
public static void main(String[] args) {
StringBuilder note = new StringBuilder("first note");
StringBuilder alias = note;
note = null;
System.out.println("Still reachable through alias: " + alias);
alias = new StringBuilder("second note");
System.out.println(alias);
}
}Still reachable through alias: first note
second noteAfter line 5 the first note is still alive, because alias refers to it. After line 7 nothing refers to "first note", so it becomes garbage.
Common Mistakes
Thinking b = a copies the object. It copies the reference. Changes through one are seen through the other.
Using == to compare object contents. Use equals.
Leaving fields null by accident. A field you forget to set in the constructor is null and crashes later, far from the real mistake.
Interview Corner
What happens when you assign one object reference to another?
Only the reference is copied. Both variables then refer to the same object, so a change made through one is visible through the other. No new object is created.
When is an object eligible for garbage collection?
When no live reference can reach it anymore: all variables that pointed to it have been reassigned, set to null or gone out of scope. The garbage collector may then reclaim its memory at a time it chooses.
Practice
- Easy: Create two
Walletreferences to the same object, change the balance through one, and print it through the other. - Harder: Write a method
static Wallet richer(Wallet x, Wallet y)that returns the wallet with the higher balance, and handles either argument beingnull.
Key Takeaways
Was this tutorial helpful?