Java course menu
Java Wrapper Classes and Autoboxing: Integer, Double, Character and More
Learn Java wrapper classes (Integer, Double, Boolean, Character, Long): why collections need them, autoboxing and unboxing, comparing Integer objects with equals, the Integer cache, NullPointerException when unboxing null, and useful static helper methods.
On this page
Java's eight primitive types (int, double, char, …) are not objects. But many parts of Java, most importantly the collections (ArrayList, HashMap, …), can only hold objects. For that, each primitive type has a matching wrapper class.
Why wrappers exist#
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
// List<int> numbers; // does not compile: type arguments must be objects
List<Integer> numbers = new ArrayList<>();
numbers.add(10); // the int 10 is wrapped automatically
numbers.add(20);
int first = numbers.get(0); // unwrapped automatically
System.out.println(first + numbers.get(1));
}
}30Autoboxing and unboxing#
Java converts between primitives and wrappers automatically:
- Autoboxing:
int→Integer, for example when adding to a list. - Unboxing:
Integer→int, for example in arithmetic.
public class Main {
public static void main(String[] args) {
Integer boxed = 42; // autoboxing
int plain = boxed; // unboxing
Integer sum = boxed + plain; // unbox, add, box again
System.out.println(sum);
Double price = 9.99;
double total = price * 3;
System.out.println(total);
}
}84
29.97Comparing wrapper objects: use equals#
== on two wrapper objects compares references, which leads to one of Java's most famous surprises:
public class Main {
public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a == b);
System.out.println(c == d);
System.out.println(c.equals(d));
System.out.println(c.intValue() == d.intValue());
}
}true
false
true
trueJava caches Integer objects for values from −128 to 127, so small values happen to share an object and == seems to work. Outside that range, each boxing creates a new object. Always compare wrapper values with equals (or unbox them first).
Unboxing null throws#
A wrapper variable can be null, but a primitive cannot. Unboxing null throws a NullPointerException:
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("pens", 40);
Integer books = stock.get("books"); // null: no such key
System.out.println(books);
try {
int count = stock.get("books"); // unboxing null
System.out.println(count);
} catch (NullPointerException e) {
System.out.println("Cannot unbox a missing value");
}
int safe = stock.getOrDefault("books", 0);
System.out.println(safe);
}
}null
Cannot unbox a missing value
0Map.getOrDefault avoids the problem. You will see maps in HashMap and TreeMap.
Useful static methods#
Wrapper classes are also toolboxes of conversion and checking methods:
public class Main {
public static void main(String[] args) {
int n = Integer.parseInt("250");
double d = Double.parseDouble("3.5");
boolean flag = Boolean.parseBoolean("TRUE");
System.out.println(n + d + " " + flag);
System.out.println(Integer.max(3, 9) + " " + Integer.toBinaryString(10) + " " + Integer.toHexString(255));
System.out.println(Integer.compare(5, 8) + " " + Integer.valueOf(7).equals(7));
System.out.println(Character.isLetter('a') + " " + Character.isDigit('5') + " " + Character.toUpperCase('q'));
System.out.println(Double.isNaN(0.0 / 0.0) + " " + Integer.MAX_VALUE);
}
}253.5 true
9 1010 ff
-1 true
true true Q
true 2147483647Integer.parseInt returns an int; Integer.valueOf returns an Integer (and uses the cache).
Performance#
Wrapper objects take more memory than primitives and add the cost of boxing. For large amounts of numeric data in tight loops, prefer primitive arrays (int[]) or primitive streams (IntStream). For ordinary collections, wrappers are perfectly fine.
Common mistakes#
Practice#
Practice exercise
Given String[] inputs = {"12", "7", "abc", "30"};, convert each valid number into a List<Integer> (skipping invalid ones), then print the list and its sum.
Show solution
import java.util.ArrayList;
import java.util.List;
public class ParseAll {
public static void main(String[] args) {
String[] inputs = {"12", "7", "abc", "30"};
List<Integer> numbers = new ArrayList<>();
for (String s : inputs) {
try {
numbers.add(Integer.parseInt(s));
} catch (NumberFormatException e) {
System.out.println("Skipping " + s);
}
}
int sum = 0;
for (int n : numbers) sum += n;
System.out.println(numbers + " sum " + sum);
}
}Skipping abc
[12, 7, 30] sum 49Key takeaway#
Finished this lesson?