# 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)**。 > 📄 来源:`packaging/Demo01.java` ### 1.2 基本类型与包装类的对应关系 | 基本数据类型 | 包装器类(引用数据类型) | |-------------|------------------------| | `byte` | `Byte` | | `short` | `Short` | | `int` | `Integer` | | `long` | `Long` | | `float` | `Float` | | `double` | `Double` | | `char` | `Character` | | `boolean` | `Boolean` | 包装器类具有属性和方法,属于引用数据类型。 > 📄 来源:`packaging/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,自动拆箱 ``` > 📄 来源:`packaging/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 方法 } ``` > 📄 来源:`packaging/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()` 方法,不要使用 `==`。 --- ## 二、集合框架入门(Collection Framework) ### 2.1 集合的概念 **集合(Collection)** 是用来存储 Java 变量、对象的容器,也称为集合容器。 与数组一样,集合也是容器,可以存储多个数据。但二者有显著区别: | 对比维度 | 数组 | 集合 | |---------|------|------| | **长度** | 一旦创建,长度不可变 | 长度可变,可动态增减 | | **存储类型** | 可存储基本数据类型和引用数据类型 | **只能存储引用数据类型**(若需存基本类型,须用对应的包装类) | | **元素类型** | 只能存储同一种数据类型(类型固定) | 可存储多种数据类型(但建议存储单一类型,以便泛型约束) | > 📄 来源:`collection/Demo01.java` ### 2.2 集合的体系结构 Java 的集合框架分为两大派系: ``` Collection(单列集合) Map(双列集合) / \ / \ List Set HashMap TreeMap /\ /\ LinkedHashMap ArrayList HashSet LinkedList TreeSet Vector LinkedHashSet ``` - **Collection**、**Map**、**List**、**Set** 都是 **接口(Interface)**,只定义规则,不实现 - 具体功能由它们的 **实现类** 完成 **Collection(单列集合)**: - **List**(有序集合):元素有顺序,可重复 - `ArrayList`:数组结构实现 - `LinkedList`:链表结构实现 - `Vector`:早期版本,线程安全 - **Set**(无序集合):元素无顺序,不可重复 - `HashSet`:哈希表实现 - `TreeSet`:红黑树实现(可排序) - `LinkedHashSet`:可保持插入顺序 **Map(双列集合)**: - 由 **键(Key)** 和 **值(Value)** 组成 - **Key** 在集合中是唯一的,不能重复 - **Value** 可以重复 > 📄 来源:`collection/Demo01.java` ### 2.3 List 与底层数据结构 集合被称为**集合框架**,因为它把底层数据结构进行了封装。 **List** 直译为"列表",对应数据结构中的**线性表结构**。线性表结构大致分为四种: #### 2.3.1 栈结构(Stack) - **特点**:先进后出(LIFO — Last In First Out) - **操作术语**: - 加入元素 → **入栈 / 压栈(push)** - 移除元素 → **出栈 / 弹栈(pop)** ``` 入栈顺序: A → B → C 出栈顺序: C → B → A ``` #### 2.3.2 队列结构(Queue) - **特点**:先进先出(FIFO — First In First Out) ``` 入队顺序: A → B → C 出队顺序: A → B → C ``` #### 2.3.3 数组结构(Array) - 在内存中开辟一段**连续的空间**存储数据 - **优点**:查询速度快,可通过索引快速定位(`arr[index]`) - **缺点**:增删速度慢,因为需要移动后续元素 - **对应实现类**:`ArrayList` ``` 索引: [0] [1] [2] [3] [4] [5] 值: 10 20 30 40 50 60 ↑ 连续存储空间 ``` #### 2.3.4 链表结构(Linked List) - 在内存中**不连续**存储,不需要开辟连续的存储空间 - 每个节点(Node)包含数据 + 指向下一个节点的指针(地址) - **优点**:增删速度快,只需改变相邻节点的指针 - **缺点**:随机查询速度慢,需要从头结点依次遍历查找 - **对应实现类**:`LinkedList` ``` 头结点 → Node1 → Node2 → Node3 → null data data data next→ next→ next→ ``` #### 2.3.5 List 实现类的数据结构对应 | 实现类 | 对应数据结构 | 查询特点 | 增删特点 | |--------|-------------|---------|---------| | `ArrayList` | 数组(Array) | 快(索引定位) | 慢(元素移动) | | `LinkedList` | 链表(Linked List)、队列(Queue)、栈(Stack) | 慢(从头遍历) | 快(改指针) | > 📄 来源:`collection/Demo02.java` --- ## 三、随堂练习要点 ### 本日课程知识点概览 | 知识点 | 说明 | 对应文件 | |--------|------|---------| | 包装类概念 | 8种基本类型→包装类,装箱/拆箱 | `packaging/Demo01.java` | | 包装类在 Bean 中的应用 | `Integer` 替代 `int` | `packaging/Person.java` | | 包装类缓存机制 | -128~127 缓存池,`==` vs `equals()` | — | | 集合框架概述 | 集合 vs 数组对比,体系结构 | `collection/Demo01.java` | | 线性表数据结构 | 栈/队列/数组/链表 特点 | `collection/Demo02.java` | ### 包装类重点 1. **概念理解**:为什么 Java 需要包装类?基本类型和包装类各有什么优劣? 2. **装箱/拆箱操作**:手动 vs 自动,理解编译器的底层转换逻辑 3. **实际应用**:在 Bean 类中优先使用包装类(如 `Integer` 替代 `int`),便于表达 `null` 语义 4. **常见陷阱**: - `==` 比较包装类时的缓存问题 - 包装类对象参与算术运算时的自动拆箱 - `null` 包装类拆箱会抛出 `NullPointerException` ### 集合框架重点 1. **理解集合 vs 数组的区别**:长度可变性、元素类型限制 2. **记忆体系结构**:Collection(List / Set)和 Map 两大分支 3. **掌握四种线性表结构**:栈(LIFO)、队列(FIFO)、数组(查询快增删慢)、链表(增删快查询慢) 4. **关联实现类**:`ArrayList` → 数组,`LinkedList` → 链表/队列/栈 --- ## 四、拓展阅读 - [Oracle Java 官方文档 — Autoboxing and Unboxing](https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html) - [Java 包装类缓存机制详解](https://www.baeldung.com/java-integer-cache) - [Oracle Java 官方文档 — Collections Framework Overview](https://docs.oracle.com/javase/8/docs/technotes/guides/collections/overview.html) - [Java 集合框架详解:List、Set、Map 的区别](https://www.baeldung.com/java-collections) - 《Java 核心技术 卷I》第 3 章 — 包装器类与自动装箱 - 《Java 核心技术 卷I》第 9 章 — 集合