☕ 第六章 Java API
📄 一句话概括

包装类 = 给 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 返回的是对象不是光杆值
⚠️ parseInt 遇到不数字的字符串

Integer.parseInt("abc") → NumberFormatException——又是 RuntimeException 家的(5.2 收容所名单 +1)。用户输入不可信,转之前心里要有数。

7. 动手环节(IDEA06 · Demo01)

  1. 新建模块包 com.itheima.api06,写 Demo01。
  2. 打印 Integer.MAX_VALUE 和 Integer.MIN_VALUE,对照 2.2 学的 int 边界。成功标准:控制台出现 2147483647 / -2147483648。
  3. 30 秒实验 ①:写 127 和 128 两组 == 比较,亲眼看 true 和 false。
  4. 30 秒实验 ②:把 == 全换成 equals → 两组都 true——雷拆了。
  5. 30 秒实验 ③:Integer score = null; int n = score; 亲眼看 NPE 报错,对照 5.1 读报错三段。
  6. 30 秒实验 ④:Integer.parseInt("abc") 看 NumberFormatException,再想想怎么防(5.5:这算使用者的 bug 还是外部风险?)。

8. 常见误区

⚠️ 五大误区
  1. 包装类之间用 == 比内容 → 缓存池陷阱,127 相等是巧合不是规律,一律 equals。
  2. 以为自动装箱"没有开销" → 背后有对象创建/缓存查询,循环里大量装箱影响性能(先知道即可)。
  3. Integer 拆箱不判 null → NPE 三大新手异常之首的惯用触发点。
  4. 把 Integer 和 int 当完全一回事 → 一个可 null 一个不可;泛型、Map 的值都只收包装类。
  5. 记不住两个特例 → int→Integer、char→Character,其余首字母变大写。

9. 本节小结

要点 内容
是什么 8 个基本类型的"对象外衣"
为什么 进集合/泛型/Object 的门 + 领 API 工具 + 能表达 null
装箱拆箱 自动写法背后是 valueOf()/intValue() 两次隐形调用
坑一 == 比地址;缓存池让 -128~127 出巧合,比内容一律 equals
坑二 null 拆箱炸 NPE,拆前判空
常用 API parseInt(字符串转数字)、MAX_VALUE、toBinaryString

10. 可折叠自测题

❓ Q1:`Integer a = 1000, b = 1000; a == b` 结果?换成 equals 呢?

== 为 false(1000 超出缓存池范围,两次 valueOf 各 new 一个新对象,地址不同);equals 为 true(比内容)。这也说明 == 的相等与否跟值有关纯属巧合,不能依赖。

❓ Q2:为什么 char 的包装类叫 Character 而不是 Char?

没有语法上的强制原因——JDK 设计者当年就是选了完整单词 Character(int 则补全成 Integer)。对新手来说这就是两条"特例":int→Integer、char→Character,考试就考这个"不按套路",背下来即可。

❓ Q3:`int n = integerList.get(0);`(假设列表第一个元素是 null)会发生什么?

自动拆箱调 intValue(),null 上调方法 → NullPointerException。防法:先判 null 再拆,或给缺考定默认值。

❓ Q4:`Integer.parseInt("3.14")` 会怎样?怎么转小数?

NumberFormatException——parseInt 只认整数字符串。转小数用 Double.parseDouble("3.14"),每个包装类都有配套的 parseXxx。

❓ Q5(毕业题):一句话讲清"Object obj = 42"里发生了什么,并说出这串知识点都串了哪几节。

编译器把 42 自动装箱为 Integer(调 Integer.valueOf(42),42 在缓存池内直接取现成对象),再把 Integer 对象装进 Object——多态"父类引用指子类对象"(4.4)+ 装箱(本节)+ 缓存池(本节)三件事同时发生;读完本节,4.5 的谜底正式收网。


11. 下一步学什么


相关笔记