|
|
@@ -0,0 +1,346 @@
|
|
|
+# JavaSE 基础 — Day11 笔记
|
|
|
+
|
|
|
+> **日期**:2026-07-27
|
|
|
+> **项目**:`c260727`
|
|
|
+> **作者**:WanJL
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 一、Java 内部类概述
|
|
|
+
|
|
|
+### 1.1 内部类分类
|
|
|
+
|
|
|
+Java 中的内部类分为三大类:
|
|
|
+
|
|
|
+| 类型 | 说明 |
|
|
|
+|------|------|
|
|
|
+| **成员内部类** | 定义在类中方法外的类,分为普通成员内部类和静态成员内部类 |
|
|
|
+| **局部内部类** | 定义在方法体或代码块中的类 |
|
|
|
+| **匿名内部类** | 没有名字的内部类,定义后直接使用 |
|
|
|
+
|
|
|
+> 📄 来源:`Demo01.java`
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、匿名内部类(核心)
|
|
|
+
|
|
|
+### 2.1 什么是匿名内部类
|
|
|
+
|
|
|
+**匿名内部类**,顾名思义,就是这个类没有名字,是匿名的,一般就是定义之后,直接使用。
|
|
|
+
|
|
|
+### 2.2 使用前提
|
|
|
+
|
|
|
+存在一个 **类** 或 **接口**,这里的类可以是普通类,也可以是抽象类。
|
|
|
+
|
|
|
+### 2.3 语法格式
|
|
|
+
|
|
|
+```java
|
|
|
+// 基于普通父类/抽象父类
|
|
|
+new 类名() {
|
|
|
+ // 重写类的方法
|
|
|
+};
|
|
|
+
|
|
|
+// 基于接口
|
|
|
+new 接口名() {
|
|
|
+ // 重写接口的方法
|
|
|
+};
|
|
|
+```
|
|
|
+
|
|
|
+> 📄 来源:`Demo01.java`
|
|
|
+
|
|
|
+### 2.4 本质
|
|
|
+
|
|
|
+匿名内部类的本质是一个继承了某个类或实现了某个接口的 **【子类的匿名对象】**。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 2.5 使用方式一:多态接收(变量赋值)
|
|
|
+
|
|
|
+将匿名内部类对象赋值给父类/接口类型的变量,通过多态调用方法。
|
|
|
+
|
|
|
+```java
|
|
|
+Usb usb = new Usb() {
|
|
|
+ @Override
|
|
|
+ public void startUsb() {
|
|
|
+ System.out.println("启动鼠标");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void closeUsb() {
|
|
|
+ System.out.println("关闭鼠标");
|
|
|
+ }
|
|
|
+};
|
|
|
+usb.startUsb();
|
|
|
+usb.closeUsb();
|
|
|
+```
|
|
|
+> 📄 来源:`Demo01.java`
|
|
|
+
|
|
|
+```java
|
|
|
+Tableware tableware = new Tableware() {
|
|
|
+ @Override
|
|
|
+ public void openTableware() {
|
|
|
+ System.out.println("打开一次性筷子");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void useTableware() {
|
|
|
+ System.out.println("使用一次性筷子");
|
|
|
+ }
|
|
|
+};
|
|
|
+person.eat(tableware);
|
|
|
+```
|
|
|
+> 📄 来源:`Test02.java`
|
|
|
+
|
|
|
+### 2.6 使用方式二:作为方法参数传递(开发中最常用)
|
|
|
+
|
|
|
+直接创建匿名内部类作为参数传入方法,无需预先定义实现类。
|
|
|
+
|
|
|
+```java
|
|
|
+NoteBook nb = new NoteBook();
|
|
|
+nb.useUSB(new Usb() {
|
|
|
+ @Override
|
|
|
+ public void startUsb() {
|
|
|
+ System.out.println("使用USB临时设备");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void closeUsb() {
|
|
|
+ System.out.println("关闭USB临时设备");
|
|
|
+ }
|
|
|
+});
|
|
|
+```
|
|
|
+> 📄 来源:`Test01.java`
|
|
|
+
|
|
|
+**优势**:如果某个实现类只想在当前场景使用一次,不想被其他人复用,使用匿名内部类可以避免创建独立的实现类文件,使代码更紧凑。
|
|
|
+
|
|
|
+### 2.7 使用方式三:直接调用方法(匿名对象调用)
|
|
|
+
|
|
|
+在匿名内部类中定义特有的方法,通过匿名对象直接调用(不经过多态)。
|
|
|
+
|
|
|
+```java
|
|
|
+new Compute() {
|
|
|
+ @Override
|
|
|
+ public int add(int a, int b) {
|
|
|
+ return a + b;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void method() {
|
|
|
+ System.out.println("匿名内部类特有的方法");
|
|
|
+ }
|
|
|
+}.method(); // 直接调用匿名内部类的特有方法
|
|
|
+```
|
|
|
+> 📄 来源:`Demo01.java`(注释部分)
|
|
|
+
|
|
|
+**注意**:这种方式因为没有变量名,所以只能调用一次。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、接口与抽象类定义
|
|
|
+
|
|
|
+### 3.1 Usb 接口
|
|
|
+
|
|
|
+定义 USB 设备的统一规范。
|
|
|
+
|
|
|
+```java
|
|
|
+public interface Usb {
|
|
|
+ void startUsb();
|
|
|
+ void closeUsb();
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Usb.java`
|
|
|
+
|
|
|
+### 3.2 Tableware 接口
|
|
|
+
|
|
|
+定义餐具的使用规范(开餐、用餐)。
|
|
|
+
|
|
|
+```java
|
|
|
+public interface Tableware {
|
|
|
+ void openTableware();
|
|
|
+ void useTableware();
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Tableware.java`
|
|
|
+
|
|
|
+### 3.3 筷子类(Tableware 接口的实现类)
|
|
|
+
|
|
|
+```java
|
|
|
+public class 筷子 implements Tableware {
|
|
|
+ @Override
|
|
|
+ public void openTableware() { }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void useTableware() { }
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`筷子.java`
|
|
|
+
|
|
|
+### 3.4 Compute 抽象类
|
|
|
+
|
|
|
+```java
|
|
|
+public abstract class Compute {
|
|
|
+ public abstract int add(int a, int b);
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Compute.java`
|
|
|
+
|
|
|
+### 3.5 Sort 接口(学生比较排序)
|
|
|
+
|
|
|
+```java
|
|
|
+public interface Sort {
|
|
|
+ Student compare(Student s1, Student s2);
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Sort.java`
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、业务类设计
|
|
|
+
|
|
|
+### 4.1 NoteBook — USB 设备管理器
|
|
|
+
|
|
|
+```java
|
|
|
+public class NoteBook {
|
|
|
+ /**
|
|
|
+ * 使用USB设备
|
|
|
+ * @param usb 接口,实际参数要传入的是实现类对象/匿名内部类对象
|
|
|
+ */
|
|
|
+ public void useUSB(Usb usb) {
|
|
|
+ usb.startUsb();
|
|
|
+ usb.closeUsb();
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`NoteBook.java`
|
|
|
+
|
|
|
+### 4.2 Person — 吃饭场景
|
|
|
+
|
|
|
+```java
|
|
|
+public class Person {
|
|
|
+ /**
|
|
|
+ * 吃饭
|
|
|
+ * @param tableware 吃饭使用的餐具
|
|
|
+ */
|
|
|
+ public void eat(Tableware tableware) {
|
|
|
+ tableware.openTableware();
|
|
|
+ tableware.useTableware();
|
|
|
+ System.out.println("开始干饭......");
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Person.java`
|
|
|
+
|
|
|
+### 4.3 Student — 学生实体类
|
|
|
+
|
|
|
+```java
|
|
|
+public class Student {
|
|
|
+ private String id;
|
|
|
+ private String name;
|
|
|
+ private Integer age;
|
|
|
+
|
|
|
+ // 构造方法、getter/setter...
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Student.java`
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、匿名内部类综合案例
|
|
|
+
|
|
|
+### 5.1 USB 设备接入案例
|
|
|
+
|
|
|
+```java
|
|
|
+// 方式一:普通创建(Demo01)
|
|
|
+Usb usb = new Usb() {
|
|
|
+ @Override
|
|
|
+ public void startUsb() { System.out.println("启动鼠标"); }
|
|
|
+ @Override
|
|
|
+ public void closeUsb() { System.out.println("关闭鼠标"); }
|
|
|
+};
|
|
|
+usb.startUsb();
|
|
|
+usb.closeUsb();
|
|
|
+
|
|
|
+// 方式二:作为参数传递(Test01)—— 开发中最常用
|
|
|
+NoteBook nb = new NoteBook();
|
|
|
+nb.useUSB(new Usb() {
|
|
|
+ @Override
|
|
|
+ public void startUsb() { System.out.println("使用USB临时设备"); }
|
|
|
+ @Override
|
|
|
+ public void closeUsb() { System.out.println("关闭USB临时设备"); }
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+### 5.2 餐具使用案例
|
|
|
+
|
|
|
+```java
|
|
|
+Person person = new Person();
|
|
|
+Tableware tableware = new Tableware() {
|
|
|
+ @Override
|
|
|
+ public void openTableware() { System.out.println("打开一次性筷子"); }
|
|
|
+ @Override
|
|
|
+ public void useTableware() { System.out.println("使用一次性筷子"); }
|
|
|
+};
|
|
|
+person.eat(tableware);
|
|
|
+```
|
|
|
+> 📄 来源:`Test02.java`
|
|
|
+
|
|
|
+**设计意图**:如果不希望接口实现类被其他人复用,使用匿名内部类可以限制其使用范围。
|
|
|
+
|
|
|
+### 5.3 学生比较排序案例
|
|
|
+
|
|
|
+```java
|
|
|
+Student s1 = new Student("1001", "张三", 20);
|
|
|
+Student s2 = new Student("1002", "李四", 25);
|
|
|
+
|
|
|
+Sort sort = new Sort() {
|
|
|
+ @Override
|
|
|
+ public Student compare(Student s1, Student s2) {
|
|
|
+ if (Integer.getInteger(s1.getId()) < Integer.getInteger(s2.getId()))
|
|
|
+ return s1;
|
|
|
+ else
|
|
|
+ return s2;
|
|
|
+ }
|
|
|
+};
|
|
|
+Student max = sort.compare(s1, s2);
|
|
|
+System.out.println(max.getName());
|
|
|
+```
|
|
|
+> 📄 来源:`Test03.java`
|
|
|
+
|
|
|
+**说明**:使用匿名内部类实现 `Sort` 接口的比较逻辑,根据学生 ID 比较大小,返回较小的学生对象。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、匿名内部类应用场景总结
|
|
|
+
|
|
|
+| 场景 | 说明 | 示例 |
|
|
|
+|------|------|------|
|
|
|
+| 接口实现类仅使用一次 | 避免创建独立的接口实现类文件 | USB设备、一次性餐具 |
|
|
|
+| 临时逻辑处理 | 实现简单的比较、回调等逻辑 | 学生比较排序 |
|
|
|
+| 方法参数需要接口/抽象类对象 | 直接传递匿名内部类简化代码 | `nb.useUSB(new Usb(){...})` |
|
|
|
+
|
|
|
+**核心优势**:
|
|
|
+1. 减少类文件数量,代码更紧凑
|
|
|
+2. 适合一次性使用的实现逻辑
|
|
|
+3. 可以直接访问外部类的成员(包括私有成员)
|
|
|
+4. 在方法参数位置直接创建,代码可读性更强
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 七、随堂练习要点
|
|
|
+
|
|
|
+> 📄 对应练习文件:`课堂练习题/20260727-内部类练习.md`
|
|
|
+
|
|
|
+本次课堂练习涵盖了以下知识点:
|
|
|
+
|
|
|
+1. **成员内部类**:定义在类中,可以直接访问外部类的私有成员
|
|
|
+2. **私有内部类**:采用私有内部类设计,对外隐藏实现细节
|
|
|
+3. **静态成员内部类**:使用 `static` 修饰,创建格式为 `外部类.内部类 变量 = new 外部类.内部类()`
|
|
|
+4. **局部内部类**:定义在方法体中,作用域仅限于当前方法
|
|
|
+5. **三种内部类综合运用**:计算机外设管理(USB + 键盘 + 鼠标)、银行账户系统
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 八、拓展阅读
|
|
|
+
|
|
|
+- [Java 匿名内部类(Anonymous Inner Class)详解](https://docs.oracle.com/javase/tutorial/java/javaOO/anonymous.html)
|
|
|
+- 内部类与 Lambda 表达式的关系(后续课程会详细讲解)
|
|
|
+- 设计模式中的策略模式(Strategy Pattern)与匿名内部类的结合使用
|