包装类 = 给 8 个基本类型配一件「对象外衣」:不穿外衣进不了集合和 Object 的门;穿上以后顺手领一堆 API 工具——但 == 陷阱和 null 拆箱两颗雷必须提前拆。
4.5 Object类("连 42 都能装进 Object"的谜底这节收网)、3.2 类与对象(一切皆对象的由来)、5.5 自定义异常类(NumberFormatException 也走家谱)。
1. 为什么需要包装类?——收 4.5 的谜底
4.5 学 Object 时留了个问号:Object obj = 42; 编译居然不报错——42 不是"光杆值"吗,怎么就成了对象?
谜底:编译器看到 42 要装进 Object,偷偷把它装箱成了 Integer 对象。基本类型(int/double/char…)快但"光杆",很多场合只收对象:
| 场合 | 基本类型行吗 |
|---|---|
| 集合/泛型(后面章节) | ✗ ArrayList<int> 编译报错,必须 ArrayList<Integer> |
| Object 及其所有 API | ✗ 只有对象能进门,42 得先穿外衣 |
| 表达"没有值" | ✗ int 的 0 是值不是"缺考";Integer 可以是 null |
2. 8 大对照表(两个特例要记住)
| 基本类型 | 包装类 | 记忆点 |
|---|---|---|
| byte / short | Byte / Short | 首字母变大写 |
| int | Integer | 唯一改名最大的(int 太短,补全成 Integer)★ |
| long / float / double | Long / Float / Double | 首字母变大写 |
| char | Character | 唯一不按套路改名的 ★ |
| boolean | Boolean | 首字母变大写 |
6 个"首字母变大写",2 个特例:int→Integer(改名补全)、char→Character(整个换词)。笔试常考。
3. 装箱与拆箱
// 手动写法(认识即可)
Integer a = Integer.valueOf(42); // 装箱:光杆值 → 对象
int n = a.intValue(); // 拆箱:对象 → 光杆值
// 自动写法(实际都用这个)
Integer b = 42; // 自动装箱,编译器偷偷调 valueOf(42)
int m = b; // 自动拆箱,编译器偷偷调 intValue()
编译器在背后干活,我们写起来和基本类型没区别——但心里要知道有两次隐形转换,坑都埋在这(见第 4、5 节)。
4. 第一大坑:Integer 的 == 陷阱(缓存池)
Integer a = 127, b = 127;
System.out.println(a == b); // true !
Integer x = 128, y = 128;
System.out.println(x == y); // false ??
底层原因:valueOf() 里有个缓存池,提前建好了 -128 ~ 127 这 256 个 Integer 对象。这个范围内的值直接发"现成房"——a 和 b 拿到的是同一个对象,== 比地址当然相等。范围外的 128,每次都 new 新对象,a 和 x 是两间不同的房,== 就是 false。
而 == 对引用类型比的是地址(4.5 的老规矩),不是内容。结论一句话:包装类比内容,永远用 equals。
5. 第二大坑:null 拆箱炸 NPE
Integer score = null; // "缺考":分数没录
int n = score; // NullPointerException!
自动拆箱 = 调 score.intValue()——空盒子上调方法,5.1 讲的空指针当场炸。拆箱前先判 null:
int n = (score != null) ? score : 0; // 缺考按 0 分算
6. 顺手领的 API 工具(以 Integer 为例)
| API | 干什么 | 示例 |
|---|---|---|
Integer.parseInt("123") |
字符串 → int(最常用) | 用户输入的都是字符串,转数字全靠它 |
Integer.MAX_VALUE / MIN_VALUE |
int 的最大/最小值 | 2147483647(2.2 讲过的边界) |
Integer.toBinaryString(10) |
转二进制字符串 | "1010"(10. 计算机基础的 Java 版) |
Integer.valueOf("123") |
字符串 → Integer | 返回的是对象不是光杆值 |
Integer.parseInt("abc") → NumberFormatException——又是 RuntimeException 家的(5.2 收容所名单 +1)。用户输入不可信,转之前心里要有数。
7. 动手环节(IDEA06 · Demo01)
- 新建模块包
com.itheima.api06,写Demo01。 - 打印
Integer.MAX_VALUE和Integer.MIN_VALUE,对照 2.2 学的 int 边界。成功标准:控制台出现 2147483647 / -2147483648。 - 30 秒实验 ①:写 127 和 128 两组
==比较,亲眼看 true 和 false。 - 30 秒实验 ②:把
==全换成equals→ 两组都 true——雷拆了。 - 30 秒实验 ③:
Integer score = null; int n = score;亲眼看 NPE 报错,对照 5.1 读报错三段。 - 30 秒实验 ④:
Integer.parseInt("abc")看 NumberFormatException,再想想怎么防(5.5:这算使用者的 bug 还是外部风险?)。
8. 常见误区
- 包装类之间用 == 比内容 → 缓存池陷阱,127 相等是巧合不是规律,一律 equals。
- 以为自动装箱"没有开销" → 背后有对象创建/缓存查询,循环里大量装箱影响性能(先知道即可)。
- Integer 拆箱不判 null → NPE 三大新手异常之首的惯用触发点。
- 把 Integer 和 int 当完全一回事 → 一个可 null 一个不可;泛型、Map 的值都只收包装类。
- 记不住两个特例 → int→Integer、char→Character,其余首字母变大写。
9. 本节小结
| 要点 | 内容 |
|---|---|
| 是什么 | 8 个基本类型的"对象外衣" |
| 为什么 | 进集合/泛型/Object 的门 + 领 API 工具 + 能表达 null |
| 装箱拆箱 | 自动写法背后是 valueOf()/intValue() 两次隐形调用 |
| 坑一 | == 比地址;缓存池让 -128~127 出巧合,比内容一律 equals |
| 坑二 | null 拆箱炸 NPE,拆前判空 |
| 常用 API | parseInt(字符串转数字)、MAX_VALUE、toBinaryString |
10. 可折叠自测题
== 为 false(1000 超出缓存池范围,两次 valueOf 各 new 一个新对象,地址不同);equals 为 true(比内容)。这也说明 == 的相等与否跟值有关纯属巧合,不能依赖。
没有语法上的强制原因——JDK 设计者当年就是选了完整单词 Character(int 则补全成 Integer)。对新手来说这就是两条"特例":int→Integer、char→Character,考试就考这个"不按套路",背下来即可。
自动拆箱调 intValue(),null 上调方法 → NullPointerException。防法:先判 null 再拆,或给缺考定默认值。
NumberFormatException——parseInt 只认整数字符串。转小数用 Double.parseDouble("3.14"),每个包装类都有配套的 parseXxx。
编译器把 42 自动装箱为 Integer(调 Integer.valueOf(42),42 在缓存池内直接取现成对象),再把 Integer 对象装进 Object——多态"父类引用指子类对象"(4.4)+ 装箱(本节)+ 缓存池(本节)三件事同时发生;读完本节,4.5 的谜底正式收网。
11. 下一步学什么
- ☑ 6.2 字符串类 ✅ —— String 铁憨憨:常量池内存图 + 不可变 + API 十件套,equals 规矩三连收网。点此复习
相关笔记
- 4.5 Object类 ← "42 装进 Object"谜底出处,本节收网
- 5.2 运行时异常与编译时异常:NumberFormatException 进收容所名单
- 10. 🔵 计算机基础/02 信息的数字化表示:MAX_VALUE、二进制背后的原理课
- 3.2 类与对象:一切皆对象,包装类是"值"向对象世界的桥