Object References and Null

Naveen AnamaneniUpdated · 5 min read

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

Assignment copies the reference, not the object
Refs.java▶ Try it
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));
    }
}
Output
a.balance = 800
same object? true

How it works

  1. Line 7 creates one Wallet object and stores a reference to it in a.
  2. Line 9: b = a copies the reference, not the object. Now two variables point to one wallet. This is called aliasing.
  3. Line 10 changes the wallet through b, so reading it through a shows 800.
  4. a == b compares 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):

NoWallet.java
Wallet c = null;
System.out.println(c == null);   // true
c.balance = 1;                    // NullPointerException
Terminal output
Exception in thread "main" java.lang.NullPointerException: Cannot assign field "balance" because "c" is null

Since 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

ExpressionAsks
a == bDo 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 == nullDoes 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.

Reach.java▶ Try it
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);
    }
}
Output
Still reachable through alias: first note
second note

After 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

  1. Easy: Create two Wallet references to the same object, change the balance through one, and print it through the other.
  2. Harder: Write a method static Wallet richer(Wallet x, Wallet y) that returns the wallet with the higher balance, and handles either argument being null.

Quick check: References

4 questions
1After Wallet b = a;, how many Wallet objects exist?
2What does a == b check for two object references?
3What happens when you call a method on a null reference?
4When can an object be garbage collected?

Key Takeaways

Was this tutorial helpful?

Lesson 96 of 482