Primitive vs Reference Types
Understand the fundamental difference between primitive types and reference types in Java.
Primitive vs Reference Types is a free Java Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Primitive vs Reference Types
Java has two fundamental categories of data types: primitive types and reference types. Understanding the difference is crucial to writing correct, efficient Java code.
The Eight Primitive Types
Java has exactly eight primitive types:
byte(8-bit integer)short(16-bit integer)int(32-bit integer)long(64-bit integer)float(32-bit decimal)double(64-bit decimal)char(16-bit Unicode character)boolean(true/false)
Primitives hold the value directly in memory — no object overhead.
int age = 25;
double price = 19.99;
boolean active = true;
char grade = 'A';
long population = 8_000_000_000L;
System.out.println(age); // 25
System.out.println(price); // 19.99
System.out.println(active); // trueReference Types
A reference type stores a memory address (reference) that points to an object on the heap. This includes:
- Classes (e.g.,
String,Scanner) - Arrays (e.g.,
int[]) - Interfaces
- Enums and Records
The variable does not hold the object — it holds a pointer to it.
String name = "Alice"; // reference to a String object
int[] scores = {90, 85, 92}; // reference to an array object
// name holds a reference, not the characters directly
System.out.println(name.length()); // 5
System.out.println(scores.length); // 3Stack vs Heap Memory
Primitive variables are stored on the stack — fast, short-lived memory tied to method calls.
Reference type objects live on the heap — larger, long-lived memory managed by garbage collection. The reference (address) itself is on the stack.
// Stack: holds the int value directly
int x = 42;
// Stack: holds reference; Heap: holds the Person object
class Person {
String name;
int age;
}
Person p = new Person(); // p is a reference on stack, object on heap
p.name = "Bob";
p.age = 30;null: The Absent Reference
Reference variables can be assigned null, meaning they point to no object. Primitives cannot be null — they always have a value.
Accessing a null reference causes a NullPointerException (NPE) — one of Java's most common runtime errors.
String s = null;
// int n = null; // Compile error — primitives can't be null
try {
System.out.println(s.length()); // NullPointerException!
} catch (NullPointerException e) {
System.out.println("Caught NPE: reference was null");
}Copy Semantics: Primitives
When you assign a primitive variable to another, Java copies the value. Changing one does not affect the other — they are completely independent.
int a = 10;
int b = a; // b gets a copy of the value 10
b = 20; // changing b does NOT affect a
System.out.println(a); // 10
System.out.println(b); // 20Copy Semantics: References
When you assign a reference variable to another, both variables point to the same object. Modifying the object through one reference is visible through the other.
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1; // arr2 points to the SAME array
arr2[0] = 99; // modifies the shared array
System.out.println(arr1[0]); // 99 — arr1 sees the change too!
System.out.println(arr2[0]); // 99Wrapper Classes: Boxing Primitives
Each primitive has a corresponding wrapper class in java.lang:
int→Integerdouble→Doubleboolean→Booleanchar→Character
Wrappers let you use primitives as objects — required for collections like List<Integer>.
Integer boxed = Integer.valueOf(42); // explicit boxing
int unboxed = boxed.intValue(); // explicit unboxing
// Autoboxing / auto-unboxing (Java does this automatically)
Integer auto = 100; // autoboxed
int val = auto; // auto-unboxed
System.out.println(Integer.MAX_VALUE); // 2147483647
System.out.println(Double.MIN_VALUE); // 5.0E-324Autoboxing Pitfalls
Autoboxing is convenient but can cause subtle bugs. Integer caches values from -128 to 127 — outside that range, == compares references, not values.
Always use .equals() to compare wrapper objects.
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true (cached)
Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false (different objects!)
System.out.println(c.equals(d)); // true (correct comparison)Passing to Methods: Pass-by-Value
Java is always pass-by-value. For primitives, the value is copied. For references, the reference (address) is copied — both point to the same object, but you cannot reassign the caller's variable from inside the method.
static void doubleValue(int n) {
n = n * 2; // only modifies the local copy
}
static void clearArray(int[] arr) {
arr[0] = 0; // modifies the shared object
}
int x = 5;
doubleValue(x);
System.out.println(x); // still 5
int[] nums = {10, 20, 30};
clearArray(nums);
System.out.println(nums[0]); // 0 — object was mutatedPractical Summary Table
Quick reference comparing primitives and reference types:
- Storage: primitive → stack value; reference → stack address + heap object
- Default value: primitive → 0/false/\u0000; reference → null
- Can be null: primitive → No; reference → Yes
- Assignment copies: primitive → value; reference → address
- In collections: primitives need wrapper classes
Quick Check
What happens when you execute the following code?
Integer x = 200; Integer y = 200; System.out.println(x == y);
Recap: Primitive vs Reference Types
Key takeaways from this lesson:
- Java has 8 primitive types stored directly on the stack
- Reference types store a heap object address; the variable holds the address
- Primitives are copied by value; references are copied by address
- Reference variables can be null; primitives cannot
- Wrapper classes (Integer, Double, etc.) box primitives as objects
- Java is always pass-by-value — even when passing references
Frequently asked questions
Is the “Primitive vs Reference Types” lesson free?
Yes — the full text of “Primitive vs Reference Types” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.
What will I learn in “Primitive vs Reference Types”?
Understand the fundamental difference between primitive types and reference types in Java. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Java Academy?
No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Primitive vs Reference Types” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Java Academy lesson?
Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Primitive vs Reference Types
- Widening and Narrowing Conversions
- The instanceof Operator
- Type Casting in Practice