Wrapper Classes & Autoboxing

Java's eight primitives are fast but they aren't objects — so they can't go in a List or be null . Wrapper classes like Integer wrap a primitive in an object, and autoboxing converts between the two automatically. Convenient — and full of subtle traps.

Learn Wrapper Classes & Autoboxing in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…

Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Before You Start

You'll need the primitive types (int, double, boolean, char...) and a first look at collections like ArrayList , which only hold objects — the main reason wrappers exist.

What You'll Learn

The Big Idea — A Gift Box for a Number

💡 Analogy: A primitive int is a bare coin sitting on the table — quick to grab, but it can't be labelled or shipped. An Integer is that same coin sealed in a small gift box: now it has a label, you can put it on a shelf alongside other boxes (a collection), and the box can be empty ( null ). Autoboxing is the machine that drops the coin in the box; unboxing takes it back out.

Every primitive has a matching wrapper: int→Integer , double→Double , boolean→Boolean , char→Character , long→Long , short→Short , byte→Byte , float→Float . They live in java.lang , so no import is needed.

1️⃣ The Eight Wrapper Classes

Each primitive maps to exactly one wrapper class. Most names just capitalise the primitive; the two exceptions are int→Integer and char→Character .

Primitive

Wrapper

Note

int

Integer

Name differs from the primitive

char

Character

double

Double

Just capitalised

boolean

Boolean

long

Long

short

Short

byte

Byte

float

Float

2️⃣ Autoboxing & Auto-Unboxing

Since Java 5, the compiler converts between a primitive and its wrapper automatically wherever the context demands it. Autoboxing wraps a primitive into an object; auto-unboxing pulls the primitive back out.

This is why you can write list.add(90) even though a List<Integer> only stores objects — the 90 is boxed for you. The convenience is real, but remember it's real method calls under the hood.

3️⃣ The == Trap (Use .equals!)

This is the most infamous wrapper gotcha. For memory efficiency, Java caches Integer objects for the range -128 to 127 . Two boxed values in that range share one cached object, so == (which compares references ) returns true . Outside the range, each box is a new object and == returns false — even when the numbers are equal.

4️⃣ The null Danger

A wrapper can hold null — useful for "no value yet". But the moment Java tries to auto-unbox a null wrapper into a primitive, it calls a method on null and throws a NullPointerException . This is one of the sneakiest NPEs because the unboxing is invisible in the source.

5️⃣ Free Utilities on Wrapper Classes

Wrapper classes aren't just boxes — they're toolboxes of static helpers you'll use constantly: parse text into numbers, read type limits, and convert between number bases.

🧩 Reorder Challenge

These lines read three String prices, parse them, and print the total. They've been shuffled — find the right order.

Declare the data and accumulator, loop and parse each string with the wrapper's static method, close the loop, then print.

🧠 Quick Recall

Predict the output before opening each answer.

Answer: true false . 127 is inside the cache (-128..127) so a and b share one object. 128 is outside it, so c and d are separate objects and == compares references.

Answer: It throws a NullPointerException . count + 1 needs to auto-unbox count to an int, but it's null — so the invisible count.intValue() call blows up before anything is printed.

Answer: 84 . parseInt turns the text "42" into the int 42, which is then doubled. (If s were "4two" it would throw a NumberFormatException instead.)

🎯 Your Turn #1 — Parse and sum

Three numbers arrive as text. Parse each with a wrapper method and print the total.

🎯 Your Turn #2 — Compare correctly

The values are 500 — outside the cache — so == gives the wrong answer. Fix the comparison to compare values.

🧩 Mini-Challenge — Nullable max

Return type Integer lets you return null for an empty list — something an int can't do. Build it from the outline.

Common Errors

Pro Tips

📋 Quick Reference

Task

Syntax

Notes

Box a primitive

Integer i = 5;

Autoboxing — Integer.valueOf(5)

Unbox to primitive

int n = i;

Auto-unboxing — i.intValue()

Compare values

a.equals(b)

Never == for wrappers!

Parse text

Integer.parseInt("12")

NumberFormatException if bad

Type bounds

Integer.MAX_VALUE

2147483647

Collection type

List<Integer>

Wrappers only, never primitives

❓ Frequently Asked Questions

🎉 Lesson Complete!

You now know every primitive's wrapper class, how autoboxing and auto-unboxing work, why collections force wrappers on you, and the two big traps — the == cache surprise and the null-unboxing NPE. You can also reach for the handy static helpers like parseInt and MAX_VALUE .

Next up: Access Modifiers — controlling who can see and use your classes, fields, and methods with public, private, and protected.

Practice quiz

What does this print? Integer a = 100; Integer b = 100; System.out.println(a == b);

  • false
  • It throws an exception
  • true
  • 100

Answer: true. Java caches Integer values from -128 to 127, so a and b share one cached object and == returns true. This is the cache trap.

What does this print? Integer c = 200; Integer d = 200; System.out.println(c == d);

  • false
  • true
  • 200
  • It throws an exception

Answer: false. 200 is OUTSIDE the cache range (-128..127), so c and d are separate objects and == compares references, giving false. Use .equals() instead.

What is autoboxing?

  • Converting a wrapper to a primitive
  • Comparing two wrappers
  • Parsing a String into a number
  • The compiler automatically converting a primitive to its wrapper, e.g. int 5 to Integer.valueOf(5)

Answer: The compiler automatically converting a primitive to its wrapper, e.g. int 5 to Integer.valueOf(5). Autoboxing wraps a primitive into its wrapper object where an object is expected; auto-unboxing is the reverse (Integer to int via intValue()).

What happens here? Integer count = null; int n = count + 1;

  • n becomes 1
  • It throws a NullPointerException when auto-unboxing null
  • n becomes null
  • It prints 0

Answer: It throws a NullPointerException when auto-unboxing null. count + 1 must auto-unbox count to an int, calling the invisible count.intValue() on null, which throws a NullPointerException.

Why does == sometimes work and sometimes fail with Integer?

  • Values -128..127 are cached and share an object, but outside that range each box is new
  • It depends on the day
  • == never works with Integer
  • It depends on the variable names

Answer: Values -128..127 are cached and share an object, but outside that range each box is new. Cached small values share one object so == is true; outside the cache each autoboxed value is a new object so == compares references. Always use .equals().

What does Integer.toBinaryString(255) return?

  • "FF"
  • "255"
  • "11111111"
  • "0xFF"

Answer: "11111111". 255 in binary is eight 1 bits: "11111111". (Integer.toHexString(255) would give "ff".)

Why does List<Integer> work but List<int> does not?

  • int is deprecated
  • Generics require object types, so primitives must use their wrapper classes
  • Integer is faster
  • List cannot hold numbers

Answer: Generics require object types, so primitives must use their wrapper classes. Generic collections can only hold objects, not primitives, so you use List<Integer>; the int elements autobox automatically on add.

What does Integer.parseInt("256") return, and what type is it?

  • "256" as a String
  • 256 as an Integer object
  • It throws an exception
  • 256 as an int

Answer: 256 as an int. parseInt turns the text "256" into the primitive int 256. (parseInt("12a") would throw NumberFormatException.)

Why is new Integer(5) discouraged in modern Java?

  • It is too slow to type
  • It is deprecated since Java 9 and always creates a new object, defeating the cache
  • It returns null
  • It throws an exception

Answer: It is deprecated since Java 9 and always creates a new object, defeating the cache. new Integer(5) is deprecated and always allocates a fresh object. Use Integer.valueOf(5) or just 5, which can reuse the cache.

When should you prefer primitives over wrappers?

  • Never - always use wrappers
  • Only inside collections
  • By default in loops, counters, and local variables, to avoid allocation and null/equality traps
  • Only when a value may be null

Answer: By default in loops, counters, and local variables, to avoid allocation and null/equality traps. Prefer primitives by default; reach for wrappers only when an API forces it (generics/collections) or when a value genuinely needs to be nullable.

Continue this course

Related lessons