Wrapper Classes & Autoboxing
Collections and generics work only with objects, not primitives — you can't have a List<int>. Each primitive type therefore has a wrapper class (Integer, Double, Boolean…), and Java converts between the two automatically. That convenience has a few traps worth knowing.
The wrapper classes
| Primitive | Wrapper |
|---|---|
int | Integer |
long | Long |
double | Double |
boolean | Boolean |
char | Character |
byte, short, float | Byte, Short, Float |
Autoboxing and unboxing
import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> scores = new ArrayList<>(); scores.add(72); scores.add(88); int first = scores.get(0); Integer boxed = 5; int sum = boxed + first; System.out.println(scores + " " + sum); } }
[72, 88] 77
Autoboxing wraps a primitive in an object when one is needed (scores.add(72)); unboxing extracts the primitive (int first = …). It happens silently in assignments, method calls and arithmetic.
Useful static methods
public class Main { public static void main(String[] args) { System.out.println(Integer.parseInt("250") + 1); System.out.println(Integer.valueOf("42")); System.out.println(Integer.toBinaryString(10)); System.out.println(Integer.toHexString(255)); System.out.println(Integer.compare(3, 7)); System.out.println(Double.isNaN(0.0 / 0.0)); System.out.println(Character.isDigit('7') + " " + Character.isLetter('x') + " " + Character.toUpperCase('q')); System.out.println(Boolean.parseBoolean("TRUE")); } }
251 42 1010 ff -1 true true true Q true
Trap 1: comparing with ==
public class Main { public static void main(String[] args) { Integer a = 100, b = 100; Integer c = 1000, d = 1000; System.out.println(a == b); System.out.println(c == d); System.out.println(c.equals(d)); } }
true false true
== on wrapper objects compares references. Java caches small values (−128 to 127), so 100 == 100 happens to be true while 1000 == 1000 isn't. Always compare wrappers with equals, or unbox them first.
Trap 2: null unboxing
import java.util.HashMap; import java.util.Map; public class Main { public static void main(String[] args) { Map<String, Integer> stock = new HashMap<>(); stock.put("mug", 12); int mugs = stock.get("mug"); System.out.println(mugs); int lamps = stock.get("lamp"); } }
12
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "java.util.Map.get(Object)" is null
at Main.main(Main.java:10)A wrapper can be null; a primitive can't. Unboxing null throws a NullPointerException. Use getOrDefault for maps (lesson 42), or check for null.
Trap 3: performance
public class Main { public static void main(String[] args) { long primitive = 0; for (int i = 0; i < 1_000_000; i++) primitive += i; Long boxed = 0L; for (int i = 0; i < 1_000_000; i++) boxed += i; System.out.println(primitive == boxed); } }
true
Both loops give the same answer, but the second creates up to a million Long objects. In hot loops, use primitives; specialised streams (IntStream, lesson 46) avoid boxing too.
When to use which
- Use primitives for local variables, fields and calculations.
- Use wrappers where objects are required: collections, generics, and when
nullgenuinely means "no value" (an optional database column, for example).
Try it yourself
Count the digits, letters and other characters in a string using Character methods.
digits=10 letters=13 other=7