là sự chuyển đổi tự động của Java giữa (, ) và các của chúng (, ). Nó tiện lợi nhưng có những pitfall tinh vi — overhead về performance, hành vi gây bất ngờ, và rủi ro .
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); // autobox int 5 → Integer (collection cần object)
int x = nums.get(0); // auto-unbox Integer → int
Nó xảy ra tự động vì collection và generic yêu cầu object (bạn không thể có List<int>), nên Java box các primitive một cách trong suốt.
Integer a = 1000;
Integer b = 1000;
a == b; // ❌ FALSE — các OBJECT Integer khác nhau (so sánh reference)
a.equals(b); // ✅ true — so sánh giá trị
// cái bẫy TỆ HƠN — Integer cache làm cho các giá trị nhỏ có vẻ hoạt động:
Integer c = 100, d = 100;
c == d; // TRUE — Java CACHE các Integer từ -128 đến 127 (cùng object)
Integer e = 200, f = 200;
e == f; // FALSE — ngoài khoảng cache → các object khác nhau
Điều này thâm hiểm: == trên Integer hoạt động với các giá trị nhỏ (được cache) nhưng thất bại với các giá trị lớn — code có vẻ đúng khi test nhưng hỏng ở production. Luôn dùng .equals() để so sánh giá trị wrapper, hoặc unbox về primitive trước.
Integer value = null; // một wrapper có thể null
int x = value; // 💥 NullPointerException — unbox null gọi null.intValue()
Map<String, Integer> map = new HashMap<>();
int count = map.get("missing"); // 💥 NPE — get() trả về null, rồi unbox thất bại
Unbox một wrapper null ném ra NPE — một crash phổ biến, gây bất ngờ, đặc biệt với các map lookup trả về null.
// ❌ autoboxing trong một hot loop — tạo hàng triệu object Integer (áp lực GC, chậm)
Long sum = 0L; // SAI type — wrapper
for (long i = 0; i < 1_000_000; i++) {
sum += i; // unbox, cộng, re-box → một Long mới mỗi vòng lặp!
}
// ✅ dùng primitive trong các hot path
long sum = 0L; // primitive — không boxing
Boxing/unboxing lặp đi lặp lại tạo ra quá nhiều object, làm tổn hại performance trong các loop chặt.
Autoboxing tiện lợi và phổ biến (collection, generic đều dựa vào nó), nhưng các pitfall của nó gây ra những lỗi thực sự, khó chẩn đoán. Cái bẫy == đặc biệt nguy hiểm: so sánh các Integer bằng == hoạt động với các giá trị nhỏ được cache (-128 đến 127) nhưng âm thầm thất bại với các giá trị lớn hơn — một lỗi vượt qua test và hỏng ở production — khiến .equals() (hoặc unboxing) trở nên thiết yếu cho việc so sánh wrapper. NullPointerException từ việc unbox các wrapper null (phổ biến với map lookup) là một crash thường gặp khác.
Và boxing trong các hot loop tạo ra các object thừa, làm tổn hại performance.
Hiểu khi nào boxing xảy ra, vấn đề so sánh giá trị-vs-reference, rủi ro unbox null, và dùng primitive trong code critical về performance là quan trọng để viết Java đúng đắn, hiệu quả — và hành vi == của Integer cache là một câu hỏi phỏng vấn kinh điển bộc lộ sự hiểu biết sâu sắc.