Что такое класс-обертка (Wrapper class) в Java?

Ответ

Класс-обертка — это объектное представление примитивного типа данных. Он инкапсулирует примитивное значение в объект.

Соответствие примитивов и оберток: Примитив Класс-обертка
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

Зачем нужны?

  1. Использование в коллекциях и дженериках, которые работают только с объектами (List<Integer>).
  2. Предоставление полезных методов (например, Integer.parseInt(), Character.isDigit()).
  3. Возможность хранения null (в отличие от примитивов).

Упаковка (boxing) и распаковка (unboxing):

// Ручная упаковка/распаковка (до Java 5)
Integer wrapped = Integer.valueOf(42); // Упаковка
int primitive = wrapped.intValue();    // Распаковка

// Автоупаковка/автораспаковка (Java 5+)
Integer autoBoxed = 42;   // Автоупаковка (int -> Integer)
int autoUnboxed = autoBoxed; // Автораспаковка (Integer -> int)

Ответ 18+ 🔞

Да ты посмотри, какая хуйня придумана! Сидишь ты такой, пишешь на Java, и тут — бац! — тебе говорят: «Все объекты, сука!». А у тебя там int, boolean, char — примитивы, не объекты. И коллекции их, блядь, не берут, и дженерики от них шарахаются. Ну пиздец, да?

Вот тут-то и вылезают эти классы-обёртки, как спасательный круг, блядь. Каждому примитиву — свой личный телохранитель-объект. Смотри, таблица, чтоб не забыл:

Примитив Класс-обёртка (его паспорт)
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

А нахуя они вообще? — спросишь ты. А вот нахуя, слушай сюда:

  1. Коллекции и дженерики — ебáные снобы. Они только с объектами вожжаются. Хочешь List из чисел? Пожалуйста, но только List<Integer>, а не List<int>. Вот такая, блядь, объектная диктатура.
  2. Методы всякие полезные. Сам int — он тупой как пробка, только значение хранит. А вот его обёртка Integer — она уже учёная, может строку в число перевести (parseInt), или Character проверит, цифра ли символ. Удобно, ёпта!
  3. null — легальный статус. Примитив boolean — он либо true, либо false, третьего не дано. А Boolean — может быть ещё и null, что иногда охуенно нужно, чтобы показать «значение неизвестно или не применимо».

А теперь самое вкусное — упаковка и распаковка. Раньше, до Java 5, это был ручной труд, адъ и израиль:

// Вот так, блядь, мучились наши отцы
Integer wrapped = Integer.valueOf(42); // Запаковал примитив в объект-коробку
int primitive = wrapped.intValue();    // Распаковал, достал обратно

А потом пришли умные дяди и сказали: «Да похуй! Пусть компилятор сам это делает». И появилась автоупаковка/автораспаковка. Теперь можно просто писать, и всё само:

Integer autoBoxed = 42;   // Смотри-ка! Компилятор сам догадался, что 42 — это int, и запаковал его в Integer. Автоупаковка, ёба!
int autoUnboxed = autoBoxed; // А тут он взял объект Integer, вытащил оттуда число и сунул в примитив. Автораспаковка, мать его!

Красота, да? Только не обольщайся. За этой магией иногда кроются ебáные грабли с производительностью (создание лишних объектов) и NullPointerException, если пытаешься распаковать null. Так что знай, где эта магия работает, а где — пиздец.