第17篇:Java常用包装类与自动装箱拆箱深入
📌 系列导航 :《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第16篇:禁止使用Lombok|
一、核心知识点
- 8种基本类型对应的包装类:
Byte、Short、Integer、Long、Float、Double、Character、Boolean - 包装类的常用方法:
parseXxx、valueOf、xxxValue、toString - 自动装箱拆箱的底层实现(
Integer.valueOf与Integer.intValue) - 包装类的缓存池(
IntegerCache、CharacterCache等) - 包装类的性能陷阱与使用建议
二、通俗讲解(1分钟开心学)
1. 为什么需要包装类?
基本类型(int、double)效率高,但它们不是对象,无法放入集合(如 ArrayList<int> 是不允许的),也无法调用方法。包装类就是给基本类型穿上一层"对象外衣",让它们也能成为对象。
2. 包装类的常用方法
- 字符串转基本类型 :
Integer.parseInt("123")、Double.parseDouble("3.14") - 基本类型转字符串 :
Integer.toString(123)或String.valueOf(123) - 包装类与基本类型互转 :
new Integer(10)(手动装箱)、intValue()(手动拆箱),但自 Java 5 后多用自动装箱拆箱。
3. 自动装箱拆箱的底层
java
Integer i = 10; // 编译后:Integer i = Integer.valueOf(10);
int j = i; // 编译后:int j = i.intValue();
4. 缓存池详解
Integer默认缓存 -128~127,Character缓存 0~127,Long缓存 -128~127,Boolean缓存TRUE和FALSE。- 使用
valueOf时,如果值在缓存范围内,返回缓存对象;否则new新对象。 new Integer(10)总是创建新对象,不经过缓存。
5. 性能陷阱
java
Integer sum = 0;
for (int i = 0; i < 10000; i++) {
sum += i; // 每次循环装箱(i -> Integer)和拆箱(sum -> int)
}
// 应该用 int sum = 0;
生活类比 :
包装类就像给螺丝钉(基本类型)配上工具箱(对象),方便运输和存放。缓存池就像常用尺寸的螺丝钉预先放在手边,不用每次都去仓库取。自动装箱就像自动把螺丝钉放进箱子,拆箱就是自动拿出来。
三、实操代码案例 + 场景说明
场景:在集合中存储数字,并进行统计计算。
java
import java.util.*;
public class WrapperDemo {
public static void main(String[] args) {
// 1. 集合中使用包装类
List<Integer> scores = new ArrayList<>();
scores.add(95); // 自动装箱 int -> Integer
scores.add(100);
// 2. 自动拆箱求和
int sum = 0;
for (Integer score : scores) {
sum += score; // 自动拆箱 Integer -> int
}
System.out.println("总分:" + sum);
// 3. 字符串与基本类型转换
int num = Integer.parseInt("123"); // 字符串转int
String str = Integer.toString(456); // int转字符串
// 4. 缓存池演示
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true,缓存对象
Integer c = 128;
Integer d = 128;
System.out.println(c == d); // false,不同对象
// 5. 比较内容用 equals
System.out.println(c.equals(d)); // true
// 6. 手动控制缓存上限(JVM参数:-Djava.lang.Integer.IntegerCache.high=1000)
// 如果设置了,128 也会命中缓存
}
}
四、避坑要点
| 错误/误区 | 后果 | 正确做法 |
|---|---|---|
用 == 比较包装类对象 |
缓存范围外比较地址,结果错误 | 使用 equals() |
| 在循环中频繁使用包装类做运算 | 创建大量临时对象,性能差 | 使用基本类型累加 |
null 包装类自动拆箱 |
NullPointerException |
先判空,或使用 Optional |
new Integer(10) 与 Integer.valueOf(10) 混用 |
不必要的对象创建 | 优先使用 valueOf(利用缓存) |
五、面试高频考点
Q1:Integer a = 100; Integer b = 100; 为什么 a==b 是 true?
Integer.valueOf(100)会从缓存中返回同一个对象,因为 100 在 -128~127 范围内。
Q2:Integer 的缓存范围可以修改吗?
可以,通过 JVM 参数
-Djava.lang.Integer.IntegerCache.high=200将上限扩大到 200。
Q3:Integer.parseInt("123") 和 Integer.valueOf("123") 有什么区别?
parseInt返回int基本类型;valueOf返回Integer对象,内部可能使用缓存。
六、练习题
- 代码填空 :
Double d1 = 0.1; Double d2 = 0.1; System.out.println(d1 == d2);输出什么?为什么? - 改错 :
Integer i = null; int j = i;会出现什么异常?如何避免? - 动手 :写一个方法,接收
List<Integer>,返回总和,要求使用基本类型累加,避免装箱开销。
📊 你的学习进度
- 当前:第17篇 / 共44篇 · 第二阶段:核心语法与面向对象(第5~20篇)
- ✅ 已完成:第1~16篇
- 📖 正在学:第17篇
- ⏳ 待学习:第18~44篇
👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇
💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!
👉 下一篇预告
《Java接口和抽象类的异同,default关键字》
内容简介:接口 vs 抽象类的详细对比,default方法的引入背景和使用场景,设计选择原则。
💡 学完这篇,你将彻底分清接口和抽象类,面试至少能说出5点区别。
📌 《Java 100 天进阶之路 | 从入门到上岗就业》 每天一篇,建议收藏 + 关注 ,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!