to automatyczna konwersja w Javie między (, ) a ich (, ). Jest to wygodne, ale ma subtelne pułapki — narzut wydajności, zaskakujące zachowanie operatora i ryzyko .
intdoubleIntegerDouble==NullPointerExceptionInteger boxed = 42; // autoboxing: int → Integer (Integer.valueOf(42))
int unboxed = boxed; // auto-unboxing: Integer → int (boxed.intValue())
List<Integer> nums = new ArrayList<>();
nums.add(5); // autoboxes int 5 → Integer (collections need objects)
int x = nums.get(0); // auto-unboxes Integer → int
Dzięki automatyczności autoboxingu, ponieważ kolekcje i generyki wymagają obiektów (nie możesz mieć List<int>), Java automatycznie opakuje typy pierwotne.
Integer a = 1000;
Integer b = 1000;
a == b; // ❌ FALSE — different Integer OBJECTS (reference comparison)
a.equals(b); // ✅ true — value comparison
// the WORSE trap — the Integer cache makes small values seem to work:
Integer c = 100, d = 100;
c == d; // TRUE — Java CACHES Integers from -128 to 127 (same object)
Integer e = 200, f = 200;
e == f; // FALSE — outside the cache range → different objects
To jest podstępne: == na Integer działa dla małych wartości (buforowanych), ale zawodzi dla dużych — kod, który wydaje się poprawny podczas testów, ulegnie awarii w produkcji. Zawsze używaj .equals() do porównania wartości obiektów opakowujących, lub najpierw rozpakuj na typy pierwotne.
Integer value = null; // a wrapper can be null
int x = value; // 💥 NullPointerException — unboxing null calls null.intValue()
Map<String, Integer> map = new HashMap<>();
int count = map.get("missing"); // 💥 NPE — get() returns null, then unboxing fails
Rozpakowanie null obiektu opakowującego wyrzuca NPE — częsta i zaskakująca awaria, szczególnie z wyszukiwaniami w mapach zwracającymi null.
// ❌ autoboxing in a hot loop — creates millions of Integer objects (GC pressure, slow)
Long sum = 0L; // WRONG type — wrapper
for (long i = 0; i < 1_000_000; i++) {
sum += i; // unbox, add, re-box → new Long each iteration!
}
// ✅ use primitives in hot paths
long sum = 0L; // primitive — no boxing
Powtarzane boxing/unboxing tworzy nadmierne ilości obiektów, co pogarsza wydajność w pętlach wykonanych wiele razy.
Autoboxing jest wygodny i wszechobecny (kolekcje, generyki — wszystko na nim polega), ale jego pułapki powodują rzeczywiste, trudne do zdiagnozowania błędy.
Pułapka == jest szczególnie niebezpieczna: porównywanie Integerów operatorem == działa dla buforowanych małych wartości (od -128 do 127), ale cicho zawodzi dla większych — błąd, który przechodzi testy i ulegnie awarii w produkcji — dlatego .equals() (lub unboxing) jest niezbędny do porównania obiektów opakowujących. NullPointerException z rozpakowania null obiektów opakowujących (częste przy wyszukiwaniach w mapach) to kolejny częsty powód awarii.
A boxing w gorących pętlach tworzy niepotrzebne obiekty, pogarsując wydajność.
Zrozumienie, kiedy boxing się dzieje, problemu porównania wartości a referencji, ryzyka rozpakowania null i używania typów pierwotnych w krytycznym dla wydajności kodzie, jest ważne dla pisania poprawnej i efektywnej Javy — a zachowanie == w przypadku Integer cache jest klasycznym pytaniem na rozmowie kwalifikacyjnej, które ujawnia głębokie zrozumienie.