# JavaSE 基础 — Day13 笔记 > **日期**:2026-07-29 > **项目**:`c260729` > **作者**:WanJL --- ## 一、包装类(Wrapper Classes) ### 1.1 为什么需要包装类? Java 中分为**基本数据类型**和**引用数据类型**。Java 的核心思想是「万事万物皆为对象」,对象就一定有属性和方法。但 Java 中的 8 种基本数据类型(`byte`、`short`、`int`、`long`、`float`、`double`、`char`、`boolean`)是从 C/C++ 延续过来的,并不符合 Java 的面向对象特性——它们没有属性、也没有方法。 为了解决这个问题,Java 为每个基本数据类型都设置了对应的引用数据类型,即**包装器类(Wrapper Classes)**。 > 📄 来源:`Demo01.java` ### 1.2 基本类型与包装类的对应关系 | 基本数据类型 | 包装器类(引用数据类型) | |-------------|------------------------| | `byte` | `Byte` | | `short` | `Short` | | `int` | `Integer` | | `long` | `Long` | | `float` | `Float` | | `double` | `Double` | | `char` | `Character` | | `boolean` | `Boolean` | 包装器类具有属性和方法,属于引用数据类型。 > 📄 来源:`Demo01.java` ### 1.3 装箱(Boxing)与拆箱(Unboxing) **装箱(Boxing)**:从基本数据类型 → 引用数据类型(包装类) **拆箱(Unboxing)**:从引用数据类型(包装类) → 基本数据类型 ```java // 手动装箱(JDK9 前的方式,之后已标记为过时) Integer integer = new Integer(a); // 装箱 // 自动装箱(JDK5+,推荐方式) Integer i = a; // int → Integer,自动装箱 Integer i1 = 15; // 直接赋值,自动装箱 // 手动拆箱 int a1 = integer.intValue(); // 调用 intValue() 方法拆箱 // 自动拆箱(JDK5+,推荐方式) int a2 = i; // Integer → int,自动拆箱 ``` > 📄 来源:`Demo01.java` ### 1.4 自动装箱与拆箱的底层原理 - **自动装箱**:编译器自动调用 `Integer.valueOf(int)` 方法 - **自动拆箱**:编译器自动调用 `Integer.intValue()` 方法 - 自动装箱/拆箱机制从 **JDK 5** 开始引入 ### 1.5 使用包装类的优势 1. **拥有属性和方法**:可以调用字符串解析、进制转换等方法 2. **泛型支持**:集合框架(如 `ArrayList`)必须使用包装类,不能使用基本类型 3. **允许 `null` 值**:包装类属于引用类型,可以为 `null`,这在数据库映射等场景中很有用 4. **工具方法**:提供了丰富的静态工具方法(如 `Integer.parseInt()`、`Integer.valueOf()` 等) ### 1.6 包装类在 Bean 类中的应用 在实际开发中,Bean 类(如 `Person`)的属性通常会使用包装类而非基本类型,原因包括: - 对象的属性可能为 `null`(数据库字段可为空) - 便于与泛型集合配合使用 - 统一使用引用数据类型,符合 OOP 风格 ```java public class Person { private String name; private Integer age; // 使用 Integer 而非 int,允许 age 为 null // getter / setter 方法 } ``` > 📄 来源:`Person.java` ### 1.7 包装类的常用方法 以 `Integer` 为例,包装类提供了一些非常实用的静态方法: | 方法 | 说明 | |------|------| | `Integer.parseInt(String s)` | 将字符串解析为 `int` | | `Integer.valueOf(int i)` | 将 `int` 转换为 `Integer`(自动装箱底层调用) | | `Integer.valueOf(String s)` | 将字符串转换为 `Integer` | | `int Integer.intValue()` | 将 `Integer` 转换为 `int`(自动拆箱底层调用) | | `Integer.MAX_VALUE` | `int` 的最大值(常量: 2147483647) | | `Integer.MIN_VALUE` | `int` 的最小值(常量: -2147483648) | 其他包装类(`Double`、`Boolean`、`Character` 等)也有类似的方法。 ### 1.8 包装类的缓存机制 部分包装类(`Integer`、`Byte`、`Short`、`Long`、`Character`)在自动装箱时存在**缓存机制**: - **Integer 缓存池**:默认缓存 `-128` ~ `127` 范围的整数 - 在此范围内,自动装箱复用同一个对象(`==` 比较为 `true`) - 超出此范围,每次自动装箱都会新建对象 ```java Integer a = 100; // 从缓存池获取 Integer b = 100; // 从缓存池获取 System.out.println(a == b); // true Integer c = 200; // 超出缓存范围,新建对象 Integer d = 200; // 超出缓存范围,新建对象 System.out.println(c == d); // false // 推荐使用 equals() 比较包装类对象的值 System.out.println(c.equals(d)); // true ``` > **注意**:包装类对象的值比较应始终使用 `equals()` 方法,不要使用 `==`。 --- ## 二、随堂练习要点 本日课程重点在于理解包装类的设计思想和使用方式: 1. **概念理解**:为什么 Java 需要包装类?基本类型和包装类各有什么优劣? 2. **装箱/拆箱操作**:手动 vs 自动,理解编译器的底层转换逻辑 3. **实际应用**:在 Bean 类中优先使用包装类(如 `Integer` 替代 `int`),便于表达 `null` 语义 4. **常见陷阱**: - `==` 比较包装类时的缓存问题 - 包装类对象参与算术运算时的自动拆箱 - `null` 包装类拆箱会抛出 `NullPointerException` --- ## 三、拓展阅读 - [Oracle Java 官方文档 — Autoboxing and Unboxing](https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html) - [Java 包装类缓存机制详解](https://www.baeldung.com/java-integer-cache) - 《Java 核心技术 卷I》第 3 章 — 包装器类与自动装箱