3. Primitives & Memory

Java Primitives, Reference Wrappers & Memory Overhead

Technical comparison of Java's 8 primitive types vs object wrappers, memory layout overhead, auto-boxing hazards, and Integer caching (-128 to 127).

📦 Primitives vs. Reference Wrapper Objects

Java maintains a split type system comprising 8 Primitive Types (stored as raw binary values) and Reference Objects (instances of classes inherited from java.lang.Object).

  • Analogy: Raw Loose Coins vs Sealed Wooden Collector Boxes.
    • Primitive (int x = 42): A raw 25-cent quarter coin sitting directly in your pocket (Stack memory). Instant access, zero wrapper overhead.
    • Wrapper Object (Integer x = 42): Wrapping that single 25-cent coin inside a heavy velvet-lined wooden collector box (Heap Object) complete with serial numbers, manual booklets, and security seals (16-byte Object Header).
                      Primitive vs Object Memory Layout

        ┌─────────────────────────────┴─────────────────────────────┐
        ▼                                                           ▼
Primitive (int x = 42)                               Reference Object (Integer x = 42)
┌──────────────┐                                     Stack: x ──► Heap Pointer
│ 4 Bytes (42) │                                                   │
└──────────────┘                                                   ▼
Fast, Stack inline                                   ┌──────────────────────────────────┐
                                                     │ 16-Byte Object Header (Mark/Klass)│
                                                     │ 4-Byte Payload Value (42)        │
                                                     └──────────────────────────────────┘

🔢 The 8 Primitive Types Reference Matrix

Primitive TypeSize (Bits / Bytes)Min ValueMax ValueDefault ValueWrapper Class
byte8 bits / 1 Byte$-128$$127$0java.lang.Byte
short16 bits / 2 Bytes$-32,768$$32,767$0java.lang.Short
int32 bits / 4 Bytes$-2^31$$2^31 - 1$0java.lang.Integer
long64 bits / 8 Bytes$-2^63$$2^63 - 1$0Ljava.lang.Long
float32 bits / 4 BytesIEEE 754IEEE 7540.0fjava.lang.Float
double64 bits / 8 BytesIEEE 754IEEE 7540.0djava.lang.Double
char16 bits / 2 Bytes\u0000 ($0$)\uffff ($65,535$)\u0000java.lang.Character
booleanJVM Dependentfalsetruefalsejava.lang.Boolean

⚡ Auto-Boxing, Unboxing & Hidden Hazards

Auto-boxing is the automatic conversion performed by the javac compiler between primitive types and their corresponding object wrapper classes (e.g., int to Integer).

// What you write:
Integer a = 100; // Auto-boxing
int b = a;       // Auto-unboxing

// What compiler generates:
Integer a = Integer.valueOf(100);
int b = a.intValue();

[!CAUTION] Hazard 1: Hidden NullPointerException on Unboxing: Attempting to unbox a wrapper object containing null throws a runtime NullPointerException!

Integer count = null;
// Throws NullPointerException! Compiler generates: int x = count.intValue();
int x = count;

[!WARNING] Hazard 2: Integer Cache Trap (-128 to 127): The JVM caches Integer instances for values between -128 and 127. Comparing wrappers with == checks reference equality, producing surprising results!

public class IntegerCacheDemo {
    public static void main(String[] args) {
        Integer a = 100;
        Integer b = 100;
        System.out.println(a == b); // TRUE (Both point to cached JVM Integer object!)

        Integer x = 200;
        Integer y = 200;
        System.out.println(x == y); // FALSE (Points to two separate Heap objects!)
        System.out.println(x.equals(y)); // TRUE (Always use .equals for objects!)
    }
}

❓ Conceptual Quizzes

Knowledge Check

Why does comparing Integer x = 200 and Integer y = 200 with 'x == y' return false, while x = 100 and y = 100 returns true?

Knowledge Check

What happens when auto-unboxing a null wrapper variable (e.g., Integer val = null; int x = val;)?


💻 Practice Problems

Problem: Defensive Auto-Unboxing Calculator

Write a method public static int safeSum(Integer a, Integer b) that safely calculates the sum of two nullable Integer wrappers, treating null arguments as 0 without throwing a NullPointerException.

On this page