Классы-обёртки
Определение
Для каждого примитивного типа есть ссылочная обёртка:
| Примитив | Обёртка |
|---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
Void соответствует ключевому слову void только как служебный ссылочный тип.
Обёртки нужны там, где API работает с объектами: в generics, коллекциях, nullable-контрактах, reflection. Они неизменяемы.
List<Integer> ids = List.of(10, 20, 30);
Integer nullableCount = null;Boxing и unboxing
Компилятор умеет автоматически оборачивать и извлекать примитив:
Integer boxed = 42; // Integer.valueOf(42)
int value = boxed; // boxed.intValue()Unboxing null приводит к NullPointerException:
Integer count = null;
// int next = count + 1; // NPE до сложенияВ горячих циклах и больших коллекциях boxing создаёт лишние объекты/ссылки и может заметно увеличить память. Поэтому Stream API имеет IntStream, LongStream и DoubleStream.
Кэш и сравнение
valueOf может возвращать кэшированный объект. Для Integer гарантирован кэш как минимум диапазона -128..127, поэтому == иногда случайно выглядит рабочим:
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true в гарантированном диапазоне
Integer x = 1000;
Integer y = 1000;
System.out.println(x == y); // не следует ожидать true
System.out.println(x.equals(y)); // true== для ссылок сравнивает идентичность, equals — значение. Для nullable-значений безопасен Objects.equals(a, b).
Парсинг и преобразование
int primitive = Integer.parseInt("42");
Integer object = Integer.valueOf("42");
String text = Integer.toString(42);
int hex = Integer.parseInt("ff", 16);Некорректная строка вызывает NumberFormatException. Integer.decode также распознаёт некоторые префиксы системы счисления, но для внешнего контракта лучше явно задавать ожидаемый формат.
Сравнение чисел
Для сортировки используйте Integer.compare, Long.compare, Double.compare, а не вычитание:
Comparator<Job> byPriority =
(left, right) -> Integer.compare(left.priority(), right.priority());Вычитание может переполниться. Для Double дополнительно важны NaN, бесконечности и различие 0.0/-0.0; контракт Double.compare задаёт устойчивый порядок.
Ловушки
- Unboxing nullable-значения.
- Сравнение обёрток через
==. - Лишний boxing в производительном коде.
- Использование обёртки как способа не продумывать отсутствие значения.
- Парсинг без обработки
NumberFormatException.
Вопросы на собеседовании
- Зачем нужны классы-обёртки?
- Что такое boxing и unboxing?
- Почему
Integer == Integerиногда возвращаетtrue, а иногдаfalse? - Что произойдёт при unboxing
null? - Чем
parseIntотличается отvalueOf?
Связанные заметки
Переменные и типы данных Java · Преобразование типов Java · Работа с числовыми данными · Класс Optional · Обобщения generics