If you've just started learning Java, you've probably heard something like this:
"Primitive variables are stored on the Stack, and Objects are stored on the Heap."
While this is a useful starting point, it's also one of the biggest sources of confusion for Java developers.
The real concept you need to understand isn't Stack vs Heap.
It's Values vs References.
Once you understand that difference, concepts like object sharing, method arguments, and Garbage Collection suddenly become much easier.
Primitive Types Store Values
Let's start with a simple example.
int age = 25;
Think of the variable as a small box.
+-------+
| age |
+-------+
| 25 |
+-------+
The variable contains the value itself.
There is no hidden object.
There is no reference.
There is no memory address you need to think about.
The number 25 is the value stored by the variable.
Another example:
int a = 10;
int b = a;
Java copies the value.
Conceptually:
+-------+ +-------+
| a | | b |
+-------+ +-------+
| 10 | | 10 |
+-------+ +-------+
Now suppose we do this:
b = 20;
Memory becomes:
+-------+ +-------+
| a | | b |
+-------+ +-------+
| 10 | | 20 |
+-------+ +-------+
Notice something important:
Changing b does not change a.
Why?
Because Java copied the value, not a connection between the variables.
Reference Types Store References
Now let's create an object.
User user = new User();
This time the variable doesn't contain the object itself.
Instead, it contains a reference to the object.
Conceptually:
user
│
▼
+----------------+
| User Object |
+----------------+
The object lives in memory, and the variable simply knows how to find it.
Copying a Reference
Now consider this code.
User u1 = new User();
User u2 = u1;
Many beginners think Java creates another object.
It doesn't.
Instead, Java copies the reference.
u1 ───┐
│
u2 ───┤
▼
+----------------+
| User Object |
+----------------+
There is still one object.
There are simply two variables referring to it.
Now suppose we write:
u2.setName("Steve");
If we later read:
System.out.println(u1.getName());
We'll also get:
Steve
Why?
Because both variables refer to the same object.
Why Doesn't Java Copy the Entire Object?
Imagine this object contains:
- a large image
- thousands of records
- megabytes of data
If Java copied the entire object every time you assigned it to another variable:
Image b = a;
your application would become extremely slow and memory hungry.
Copying a reference is cheap.
Copying an entire object can be expensive.
That's one of the main reasons Java uses references.
A Helpful Analogy
Imagine a hotel.
The room number is:
305
The guest is inside the room.
If you write down:
305
did you copy the guest?
No.
You only copied the room number.
A Java reference works the same way.
The variable stores information that allows Java to locate the object.
What Happens When a Reference Becomes null?
Consider this example.
User user = new User();
user = null;
Did the object disappear immediately?
No.
The object may still exist in memory.
What changed is that the variable no longer refers to it.
If no reachable references remain, the object becomes:
Eligible for Garbage Collection
Notice the wording.
Eligible does not mean:
"Deleted immediately."
It simply means the JVM is now allowed to reclaim its memory whenever it decides it's appropriate.
Garbage Collection Uses Reachability
One of the most common misconceptions is that Java counts references.
It doesn't.
The JVM starts from a set of special locations called GC Roots (such as active thread stacks and static fields) and asks one question:
Can I still reach this object?
If the answer is:
- Yes → The object is alive.
- No → The object is eligible for garbage collection.
This is why even objects that reference each other can still be collected if nothing in the running program can reach them.
The Mental Model That Changed Everything
Whenever you're unsure what's happening, remember these two rules:
Primitive Types
Variable
↓
Value
Reference Types
Variable
↓
Reference
↓
Object
That's it.
This simple mental model explains:
- why objects can be shared,
- why changing one reference affects another,
- why
nulldoesn't immediately delete an object, - and why Java needs Garbage Collection.
Final Thoughts
Many developers spend years memorizing syntax but never build a clear mental model of memory.
Once you understand the difference between values and references, Java becomes much more predictable.
The next time you write:
User u2 = u1;
don't think:
"I created another object."
Think:
"I created another reference to the same object."
That small change in thinking is one of the biggest milestones in becoming a confident Java developer.