StudyToCert

All certifications / OCP Java / Lessons

Oracle Certified Professional: Java SE Developer 1Z0-831 (Java SE 25) · Domain 1: Handling date, time, text, numeric and boolean values

Wrapper classes, autoboxing/unboxing and Integer caching with ==

▶ Watch the overview video

Last reviewed September 25, 2026 · Leer en español

Each primitive type has a wrapper class in java.lang: Byte, Short, Integer, Long, Float, Double, Character and Boolean. Wrappers exist because collections and generics work only with objects, so you cannot write List<int>. A wrapper object is immutable and can also be null, which a primitive cannot.

Autoboxing is the compiler automatically converting a primitive to its wrapper, and unboxing is the reverse. When you write Integer n = 5; the compiler inserts Integer.valueOf(5), and when you write int m = n; it inserts n.intValue(). Unboxing a null reference therefore throws a NullPointerException at runtime, a frequent exam scenario with Map.get returning null into an int variable.

Know the difference between the two conversion families. Integer.parseInt("42") returns a primitive int, while Integer.valueOf("42") returns an Integer object. The wrapper constructors such as new Integer(5) are deprecated and marked for removal, so modern code and exam answers use valueOf or autoboxing. Boxing only goes to the matching wrapper: Long x = 5; does not compile, because 5 is an int and would need to become an Integer, which is not a Long.

The == operator on two wrapper references compares identity (whether they are the same object), not value. Integer.valueOf keeps a cache of Integer objects for at least the range -128 to 127, and autoboxing uses valueOf, so two boxed values in that range usually point at the same cached object. Outside that range each boxing typically creates a new object. That is why Integer a = 127, b = 127; a == b is true but the same test with 128 is false. Short, Long and Byte cache the same range, Character caches 0 to 127, and Boolean has only TRUE and FALSE. The fix is simple: compare wrapper values with equals.

Mixing a wrapper and a primitive in == is different: the wrapper is unboxed, so the comparison is numeric and the cache does not matter. Also watch equals across types. Long.valueOf(1).equals(1) is false, because the argument is boxed to an Integer, and Long.equals returns false for anything that is not a Long.

Integer a = 100, b = 100;
Integer c = 1000, d = 1000;
System.out.println(a == b);      // true  (cached)
System.out.println(c == d);      // false (different objects)
System.out.println(c.equals(d)); // true
int e = 1000;
System.out.println(c == e);      // true  (c is unboxed)

Overload resolution also involves boxing. The compiler first looks for an exact or widening match, then tries boxing and unboxing, and only then varargs. So given m(long) and m(Integer), the call m(5) picks m(long), because widening beats boxing.

Key terms

Wrapper class
An immutable class such as Integer or Double that holds one primitive value as an object.
Autoboxing
The automatic conversion of a primitive to its wrapper, done by the compiler through valueOf.
Unboxing
The automatic conversion of a wrapper to its primitive; throws NullPointerException if the reference is null.
Integer cache
A pool of Integer objects for at least -128 to 127 that Integer.valueOf reuses, which makes == appear to work for small values.
Real-world example

A shop counts orders per customer in a Map<String, Integer>. The code int count = counts.get(id); works in testing, then crashes in production with a NullPointerException the first time a new customer appears, because get returns null and the unboxing fails. Using getOrDefault(id, 0) avoids it.

Exam tip: When you see == between two Integer variables, check whether both values fall in -128 to 127. If they do, expect true; if not, expect false. If one side is a primitive, it is a plain numeric comparison.

Check yourself

What does Integer x = 128, y = 128; System.out.println(x == y); print?

Usually false. 128 is outside the guaranteed cache range, so each boxing creates a separate object and == compares identity.

Does Long total = 10; compile?

No. 10 is an int, and autoboxing only produces an Integer, which is not assignable to Long. Write 10L.

What happens when Integer n = null; int m = n; runs?

It compiles but throws a NullPointerException, because unboxing calls intValue() on null.

Study OCP Java for free
A week-by-week plan with every lesson, quizzes, checkpoint tests, a practice exam and hands-on labs.
Open the OCP Java study plan