《Java 100 天进阶之路》第5篇:装箱和拆箱
第5篇:装箱和拆箱
📌 系列导航:《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第4篇:秒懂数组拷贝,感知新境界 |
➡️ 下一篇:第6篇:Java异常有哪几种
一、核心知识点
- 基本类型 vs 包装类(
int↔Integer,double↔Double等) - 手动装箱/拆箱(
new Integer(10)/intValue()) - 自动装箱拆箱机制(Java 5引入)
- 包装类的缓存池(
IntegerCache,-128~127) - 性能陷阱与
null风险
二、通俗讲解(1分钟开心学)
1. 为什么需要包装类?
基本类型(int、double)效率高,但它们不是对象,无法放入集合(如ArrayList<int>是不允许的)。包装类(Integer、Double)就是把基本类型“包”成对象,可以放进集合,也能调用方法(如Integer.parseInt)。
2. 装箱和拆箱是什么?
- 装箱:把基本类型变成包装对象。像把一颗螺丝钉装进一个工具箱里。
- 拆箱:从包装对象里取出基本类型。像打开工具箱拿出螺丝钉。
Java 5之前,你必须手动装箱:
Integer i = new Integer(10); // 手动装箱
int j = i.intValue(); // 手动拆箱
Java 5以后,编译器自动帮你装箱和拆箱:
Integer i = 10; // 自动装箱(编译成 Integer.valueOf(10))
int j = i; // 自动拆箱(编译成 i.intValue())
生活类比:
自动装箱就像超市自助结账——你把商品(基本类型)放在扫描区,机器自动把它“包装”成小票(包装类);拆箱就像你把小票上的商品价格取出来,机器自动帮你计算。
3. 缓存池陷阱(面试常考)
Integer内部有一个缓存池,默认缓存了-128~127之间的整数。当你使用自动装箱时,如果数值在这个范围内,会直接返回缓存的对象;如果超出范围,会创建新对象。
Integer a = 127; // 从缓存取
Integer b = 127; // 从缓存取
System.out.println(a == b); // true(同一个对象)
Integer c = 128; // new Integer(128)
Integer d = 128; // new Integer(128)
System.out.println(c == d); // false(不同对象)
记住:比较包装类的内容,永远用equals(),不要用==。
三、实操代码案例 + 场景说明
场景:你需要在
ArrayList中存储数字,并计算总和。
import java.util.ArrayList;
public class BoxingDemo {
public static void main(String[] args) {
ArrayList<Integer> scores = new ArrayList<>();
// 自动装箱:int -> Integer
scores.add(95);
scores.add(87);
scores.add(100);
int sum = 0;
for (Integer score : scores) {
// 自动拆箱:Integer -> int
sum += score;
}
System.out.println("总分:" + sum);
}
}
使用==比较包装类的危险示范:
Integer x = 100;
Integer y = 100;
System.out.println(x == y); // true(缓存内)
Integer m = 200;
Integer n = 200;
System.out.println(m == n); // false(缓存外)
// 正确做法
System.out.println(m.equals(n)); // true
四、避坑要点
| 错误/误区 | 后果 | 正确做法 |
|---|---|---|
| 在循环中用包装类做累加 | 每次循环都装箱拆箱,创建大量临时对象,性能差 | 循环内使用基本类型累加,最后再装箱 |
对null的包装类进行自动拆箱 |
NullPointerException |
先判空,或使用Optional包装 |
用==比较包装类 |
缓存范围外的值会误判 | 始终使用equals()比较内容 |
以为Integer i = null; int j = i;会优雅失败 |
程序崩溃 | 避免不安全的拆箱,或显式判断 |
性能反面示例(不要这样写):
Integer sum = 0;
for (int i = 0; i < 10000; i++) {
sum += i; // 每次循环装箱+拆箱
}
// 应该用 int sum = 0;
五、面试高频考点
Q1:什么是自动装箱和拆箱?
编译器自动将基本类型转换为包装类(调用
valueOf())称为装箱,反向(调用xxxValue())称为拆箱。从Java 5开始支持。
Q2:Integer a = 127; Integer b = 127; 为什么a==b是true?
Integer.valueOf()方法对-128~127范围内的值使用了缓存,多次调用返回同一个实例。超出范围则new新对象。
Q3:下列代码输出什么?
Integer i1 = new Integer(10);
Integer i2 = 10;
System.out.println(i1 == i2);
false。new强制创建新对象,而自动装箱10在缓存范围内,但缓存的对象与new的对象不是同一个。
六、练习题
- 简答:解释
Integer i = 128; int j = 128; System.out.println(i == j);输出什么?为什么(提示:拆箱后比较值)? - 代码优化:以下代码有什么性能问题?如何修改?
Long sum = 0L; for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += i; } - 动手:写一个小程序,通过
-Djava.lang.Integer.IntegerCache.high=1000JVM参数,将Integer缓存上限扩大到1000,验证200是否命中缓存。
📊 你的学习进度
- 当前:第5篇 / 共44篇 · 第二阶段:核心语法与面向对象(第5~20篇)
- ✅ 已完成:第1~4篇
- 📖 正在学:第5篇
- ⏳ 待学习:第6~44篇
👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇
💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!
👉 下一篇文章预告
《Java异常有哪几种》
内容简介:检查型异常、运行时异常、Error 有什么区别?什么时候该用 try-catch,什么时候该改代码?
💡 学完这篇,你将彻底分清异常体系,写出更健壮的代码。
📌 《Java 100 天进阶之路 | 从入门到上岗就业》 每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!
更多推荐




所有评论(0)