Basic Syntax
Wrapper Classes
Explore the object representations of primitive types, covering autoboxing, unboxing, caching mechanisms, and performance overheads.
Interview: Crucial for understanding collections integration, NullPointerExceptions during unboxing, and the Integer Cache range pool.
In Java, primitive data types (like int, double, and char) are not objects. While they are highly performant and memory-efficient, they cannot be used in Java collections (like ArrayList or HashMap) or as nullable values. Wrapper Classes wrap primitives in objects, bridging the gap between primitive efficiency and object-oriented flexibility.
Core Idea
Each primitive has a corresponding Wrapper Class (e.g., int to Integer). Autoboxing and unboxing automate conversion between the two.
Why It Matters
Java's generics require object types. Without wrappers, you cannot store primitives in standard Java collections. Wrappers also support utility methods and null values.
Interview Lens
Expect deep-dive questions on the Integer Cache (value pooling), memory overhead differences, and unboxing-induced NullPointerExceptions.
Primitive to Wrapper Mapping
Java provides eight wrapper classes in the java.lang package:
| Primitive Type | Wrapper Class | Size in Memory (Primitive) | Size in Memory (Wrapper) |
|---|---|---|---|
byte |
Byte |
1 byte | ~16 bytes (Heap overhead) |
short |
Short |
2 bytes | ~16 bytes |
int |
Integer |
4 bytes | ~16 bytes |
long |
Long |
8 bytes | ~24 bytes |
float |
Float |
4 bytes | ~16 bytes |
double |
Double |
8 bytes | ~24 bytes |
char |
Character |
2 bytes | ~16 bytes |
boolean |
Boolean |
1 bit (JVM dependent) | ~16 bytes |
Autoboxing and Unboxing
Java automatically converts between primitive types and their corresponding wrapper classes:
- Autoboxing: The automatic conversion that the Java compiler makes between the primitive type and its corresponding object wrapper class. For example, converting an
intto anInteger. Under the hood, the compiler inserts calls toInteger.valueOf(primitiveValue). - Unboxing: The automatic conversion of wrapper class objects back into primitives. For example, converting an
Integerto anint. Under the hood, the compiler inserts calls tointegerObject.intValue().
The Integer Cache (Value Pooling)
To save memory and improve performance, Java pools/caches wrapper instances of low-value integer classes. When using autoboxing or calling Integer.valueOf(), Java returns cached references for values in the range -128 to 127 (inclusive).
This caching behavior applies to:
Byte,Short,Long,Integer(range -128 to 127)Character(range 0 to 127)Boolean(cachingTRUEandFALSEconstants)
Comparing wrapper objects outside this range using the identity operator (==) will compare their heap memory references and evaluate to false, even if their wrapped numerical values are identical.
Common Pitfalls
- Comparing Wrappers with
==: Using==compares references, not values. For example,Integer x = 200, y = 200; x == yisfalse. Always usex.equals(y)to compare object values. - NullPointerExceptions (NPE) on Unboxing: Trying to unbox a wrapper object that is
nullcauses a runtimeNullPointerException. For example,Integer x = null; int y = x;will compile but crash at runtime. - Performance and GC Overhead in Loops: Autoboxing inside loops creates a large number of temporary objects, triggering frequent garbage collection cycles. For example, declaring
Long sum = 0L;instead oflong sum = 0L;inside a loop with millions of iterations.
Best Practices
- Use primitives for local variables, loop indexes, and mathematical calculations where null is not needed.
- Use wrapper classes for fields in domain objects/entities where
nullrepresents a database NULL or missing value. - Always compare wrapper values using
.equals(), never==, unless you specifically need reference identity. - Perform null checks on wrapper objects before unboxing or using them in conditional statements.
- Use utility parsing methods like
Integer.parseInt(str)(returns primitiveint) instead ofInteger.valueOf(str)(returnsIntegerobject) when you need a primitive.
Interview-Relevant Information
Q1: Why does Integer a = 100, b = 100; a == b evaluate to true, but Integer c = 200, d = 200; c == d evaluates to false?
Answer: Java caches Integer wrapper class objects for values between -128 and 127. Autoboxing 100 returns the same cached reference from the pool, so a == b is true. For 200, autoboxing generates new object references on the heap, so c == d compares memory addresses and yields false.
Q2: What happens when you execute: Double d = null; double val = d; ?
Answer: It compiles successfully because unboxing is supported. However, at runtime, the JVM calls d.doubleValue() to retrieve the primitive. Since d is null, this invocation throws a NullPointerException.
Q3: Can the Integer Cache range limits be adjusted?
Answer: Yes. You can change the upper limit of the Integer cache by passing the JVM argument -XX:AutoBoxCacheMax=<size>. The lower limit is permanently fixed at -128.
Quick Checklist
Can you explain autoboxing/unboxing mechanisms, define the caching range for Integer, Byte, and Character, explain how comparison behavior changes across the cache boundary, and prevent unboxing NPEs? If yes, you have mastered Wrapper Classes.
Use Cases
Using primitive fields in database entities where null represents an unassigned or empty state.
Storing integer counters or boolean markers in ArrayLists, HashMaps, or other Generics collections.
Common Mistakes
Accidentally comparing wrapper numbers using comparison operators (like ==) inside configuration files or critical business logic.
Declaring variables as wrappers (e.g., Double) inside recursive or tight computational loops, degrading garbage collection performance.