В чем разница в производительности между примитивным типом и его классом-оберткой в Java?

Ответ

Использование примитивных типов (int, long, boolean) значительно эффективнее, чем их классов-оберток (Integer, Long, Boolean), по нескольким причинам:

Критерий Примитивный тип (например, int) Класс-обертка (например, Integer)
Хранение В стеке (stack memory). В куче (heap memory).
Память 4 байта. ~16 байт (заголовок объекта + ссылка).
Операции Прямые арифметические операции. Требуют автоупаковки/распаковки (autoboxing/unboxing), создающей временные объекты.
Сравнение == сравнивает значения. == сравнивает ссылки; для значений нужно использовать .equals() или == после unboxing.

Практический пример разницы в производительности:

// Быстро: операции только с примитивами в стеке
long sumPrimitive = 0L;
for (int i = 0; i < 1_000_000; i++) {
    sumPrimitive += i; // Простое сложение
}

// Медленно: накладные расходы на автоупаковку и сборку мусора
Long sumWrapper = 0L; // Неявная упаковка long -> Long
for (int i = 0; i < 1_000_000; i++) {
    sumWrapper += i; // Каждая итерация: i упаковывается в Integer, затем в Long
}

Второй цикл может работать в 5-10 раз медленнее из-за создания миллионов временных объектов Long и нагрузки на Garbage Collector.

Рекомендация: Используйте классы-обертки только когда это необходимо (например, для хранения в коллекциях List<Integer>, работы с дженериками или представления null-значений).

Ответ 18+ 🔞

Да ты посмотри, на что люди время тратят! Сидят, блядь, думают: взять примитив int или его обёртку Integer? А разница-то, сука, как между пальцем и хуем с горы!

Вот смотри, табличку для особо одарённых нарисовали, чтоб до самых тупых дошло:

Критерий Примитив (ну, int) Обёртка (этот ваш Integer)
Где лежит В стеке, всё под рукой. В куче, блядь, далеко, за семью замками.
Сколько жрёт 4 байта, как пить дать. Аж ~16 байт, ёпта! Целый объект с головой и ногами!
Как работает Сложил, вычел — и всё, красота. Тут тебе и упаковка, и распаковка, и мусора куча.
Как сравнивать == и в ус не дуешь. == — ссылки сравнишь, а значения нет. Нужен .equals() или распаковывай, мудила!

А теперь, блядь, живой пример, чтоб мозги встали на место:

// Быстро, как хуй в проруби!
long sumPrimitive = 0L;
for (int i = 0; i < 1_000_000; i++) {
    sumPrimitive += i; // Чистая математика, нихуя лишнего.
}

// Медленно, блядь, до одури!
Long sumWrapper = 0L; // Тут уже пиздец начался — неявная упаковка!
for (int i = 0; i < 1_000_000; i++) {
    sumWrapper += i; // Каждый раз, сука: i -> Integer, потом в Long, мусор, шум, гам!
}

Второй цикл, ёпта, может и в 10 раз тормознее быть! Потому что создаётся овердохуища временных объектов, а Garbage Collector потом охуевает, убирая этот бардак.

Так что запомни, как "Отче наш": Обёртки — только когда приперло. Коллекции (List<Integer>), дженерики или если нужно null запихнуть — тогда да. А так — используй примитивы, и будет тебе счастье, а не волнение ебать!