Обёртки примитивов в Java: boxing, unboxing и null
💻 Информатика · 10 класс
Integer вместо int, автоматические преобразования и безопасное сравнение значений.

Зачем существуют классы-обёртки
В Java int, double, boolean и другие примитивы не являются объектами. Для них предусмотрены соответствующие ссылочные типы: Integer, Double, Boolean, а также Byte, Short, Long, Float и Character. Они нужны, например, в обобщённых коллекциях: List<Integer> допустим, List<int> — нет. Массив int[] при этом является объектом, хотя его элементы — примитивы.
Два направления преобразования
Boxing преобразует примитивное значение в обёртку; unboxing извлекает примитив. Компилятор может вставить такие преобразования автоматически:
Integer stored = 7; // boxing
int value = stored; // unboxing
System.out.println(value + 1);Результат — 8. При сложении нужно числовое значение, поэтому обёртка распаковывается. Для явного получения Integer обычно используют Integer.valueOf(7), а не устаревший конструктор new Integer(7).
Разобранный пример с null
Integer missing = null;
int number = missing;Вторая строка вызывает NullPointerException: у null невозможно извлечь значение int. Ошибка не означает, что int умеет хранить null. Проблема возникла раньше — при автоматической распаковке ссылочного значения.
Если отсутствие числа допустимо, нужно явно определить поведение. Например:
Integer savedScore = null;
int score = savedScore == null ? 0 : savedScore;Получится 0, поскольку выбранная ветвь не распаковывает null. Но ноль — решение автора программы, а не универсальное значение «нет данных». В другой задаче правильнее сообщить об отсутствии результата, чтобы не спутать его с настоящим нулевым баллом.
Почему == ненадёжен для сравнения обёрток
Когда оба операнда ссылочные, == проверяет тождество объектов, а не просто числовое равенство. Для части малых значений используются общие объекты; из-за этого случайный тест может создать ложную уверенность. Для значений применяют equals, а с возможным null — Objects.equals(a, b). Сравнение Integer с int может включать распаковку и снова требует внимания к null.
Практика
- Что выведет Integer x = 12; int y = x; затем println(y * 2)?
- Почему List<Integer> может содержать null, а переменная int — нет?
- Как сравнить два Integer a и b по значениям, если один из них может отсутствовать?
Ответы
1. 24: значение 12 упаковано, затем распаковано и умножено на 2. 2. Integer — ссылочный тип, для которого возможен null; int представляет примитивное целое число. Допустимость null в конкретной коллекции зависит ещё и от её реализации. 3. Objects.equals(a, b); вызов a.equals(b) небезопасен при a == null.
Частые ошибки
Не используйте null как «особое число» без проверки перед арифметикой. Не доказывайте корректность == одним примером с маленькими числами. И не выбирайте обёртки повсюду автоматически: примитив и объект имеют разные задачи и стоимость представления.