skip to content

Wrapper Classes

The object counterparts of the primitives: why they exist, how autoboxing works, parsing, caching and the comparison pitfalls that follow. Interviewers use them for quick puzzles about == and null.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

Why do wrapper classes like Integer and Double exist in Java when there are already primitive types like int and double?

level: juniorimportance: must knowfreq 70%

answer

  1. Generics/collections need objects, not int
  2. Wrappers can be null; primitives cannot
  3. Home for static helpers + MIN/MAX constants
  4. Autoboxing bridges the two worlds
  5. Primitives = faster/smaller, wrappers = flexible

basics

~20 s

Primitives like int are not objects, so they can't be stored in collections (e.g. List) or used as generic types, and can't be null. Wrapper classes turn a primitive into an object so it can.

solid answer

~40 s

Java has two parallel type families: primitives (int, double, boolean, char, etc.), which are fast value types, and their object wrappers (Integer, Double, Boolean, Character...). Wrappers exist because many parts of Java only work with objects: the collections framework and generics (List<Integer>, Map keys/values) cannot hold primitives, and only an object reference can be null to signal 'no value'. Wrappers also carry useful static utilities and constants (parseInt, valueOf, MIN_VALUE, compare). The cost is that a wrapper is a heap object with reference overhead, so primitives are preferred in tight numeric code; autoboxing converts between the two automatically. So you reach for wrappers when you need nullability, generics, or collection membership, and primitives otherwise.

go deeper

for a junior

Knows the eight primitives have matching wrapper classes and that wrappers let numbers go into collections and be null.

for a middle

Explains generics/collections require objects, nullability semantics, and that autoboxing bridges the two with NPE/perf caveats.

for a senior

Articulates the design trade-off (memory/identity/null) and gives concrete guidance on when to pick which, plus boxing costs in hot paths.

for a principal

Frames the primitive/wrapper split as a language design decision, discusses its performance implications at scale, and references how Project Valhalla (value classes) aims to erase the gap.

## What a primitive is A **primitive type** in Java is a built-in value type that is NOT an object. The eight primitives are `byte`, `short`, `int`, `long`, `float`, `double`, `boolean`, and `char`. A variable of a primitive type holds the actual value directly (e.g. the variable `int x` literally contains the bits for the number), it lives compactly on the stack or inline in an object, it can never be `null`, and it has no methods you can call on it. ## What a wrapper class is For each primitive there is a corresponding **wrapper class** in `java.lang`: `Byte`, `Short`, `Integer`, `Long`, `Float`, `Double`, `Boolean`, `Character`. A wrapper is a normal Java object that holds a single primitive value inside it. Because it is an object, a wrapper variable holds a **reference** (a pointer) to a heap object, it CAN be `null`, and the class can provide methods and static helpers. ## Why wrappers are needed 1. **Generics and collections work only with reference types.** Java generics (the `<...>` type parameters) were designed to operate on objects, not primitives. You cannot write `List<int>` or `Map<int, String>`; you must write `List<Integer>`, `Map<Integer, String>`. The collections framework (`ArrayList`, `HashMap`, `HashSet`...) stores `Object` references internally, so anything you put in a collection must be an object. Wrappers are how a number 'becomes an object' to enter a collection. 2. **Nullability — representing 'no value'.** A primitive `int` always has a value (default `0`). It cannot say 'I have no value'. A wrapper reference can be `null`, which is essential for things like a database column that may be NULL, an optional field, or 'the user did not provide a number'. `int score = 0` is ambiguous (did they score zero, or not play?); `Integer score = null` is unambiguous. 3. **Static utility methods and constants.** Each wrapper class is the natural home for helper methods that operate on that kind of value: `Integer.parseInt("42")`, `Integer.valueOf(...)`, `Integer.compare(a, b)`, `Integer.toBinaryString(...)`, plus constants `Integer.MIN_VALUE` and `Integer.MAX_VALUE`. These have nowhere to live on a bare primitive. ## Autoboxing and unboxing Since Java 5, the compiler automatically converts between the two worlds. **Autoboxing** turns a primitive into its wrapper (`Integer i = 5;` compiles to `Integer i = Integer.valueOf(5);`). **Unboxing** turns a wrapper back into a primitive (`int n = i;` compiles to `int n = i.intValue();`). This makes the two families feel interchangeable, but the conversion is real work and has two traps: unboxing a `null` wrapper throws `NullPointerException`, and boxing in a loop creates many short-lived objects. ## The trade-off Primitives are smaller and faster (no object header, no pointer indirection, no garbage to collect), so numeric-heavy code should use primitives. Wrappers add nullability, generics/collection compatibility, and utility methods at the cost of memory and a little speed. Rule of thumb: **use primitives by default; use wrappers when you need null, generics, or collection membership.**

  • Why can't you write List<int> in Java?
    Generics operate on reference types (objects) only; collections store Object references internally. int is a primitive, not an object, so you must use the wrapper List<Integer>.
  • Give a concrete case where nullability of a wrapper matters.
    A field mapped to a nullable database column, or an unset optional value: Integer count = null distinguishes 'no value' from a real 0, which an int cannot express.

A primitive is cash in your hand — instant to use but you can't mail it. A wrapper is the cash sealed in an addressed envelope (an object): now it can travel through the postal system (collections/generics) and the envelope can also be empty (null).

saying these in an interview costs you the question

  • Saying wrappers and primitives are 'the same thing' — they differ in identity, nullability, and memory layout
  • Claiming you should always use Integer over int — primitives are preferred for performance and to avoid NPEs
  • Thinking a wrapper stores the value 'on the stack like a primitive' — it is a heap object referenced by a pointer

context

open as a page

What is the difference between Integer.parseInt("42") and Integer.valueOf("42")?

level: middleimportance: must knowfreq 75%

basics

~10 s

parseInt returns a primitive int. valueOf returns an Integer object (a wrapper). Both parse the text the same way, but you get different return types.

open as a page

What hidden costs and pitfalls does autoboxing of wrapper classes introduce, and how would you avoid them in performance-sensitive or correctness-sensitive code?

level: seniorimportance: must knowfreq 60%

basics

~20 s

Autoboxing silently turns primitives into objects, which can (1) throw NullPointerException when a null wrapper is unboxed, (2) allocate many objects in loops hurting performance, and (3) make == compare object identity instead of value. Use primitives where possible and equals() to compare.

open as a page

Why is new Integer(5) deprecated, and what should you use instead?

level: middleimportance: should knowfreq 55%

basics

~10 s

new Integer(5) always creates a brand-new object and wastes memory. Use Integer.valueOf(5) (or just autoboxing, Integer x = 5;) instead, which can reuse cached objects.

open as a page

What static utility methods and constants do wrapper classes provide, and why use Integer.compare(a, b) instead of writing your own comparison?

level: seniorimportance: should knowfreq 50%

basics

~10 s

Wrappers offer static helpers (parseInt, valueOf, toString, compare, min/max, toBinaryString) and constants like Integer.MIN_VALUE and Integer.MAX_VALUE. Integer.compare(a, b) safely returns negative/zero/positive without the overflow bug of a - b.

open as a page