|
|
@@ -0,0 +1,317 @@
|
|
|
+# JavaSE 基础 — Day10 笔记
|
|
|
+
|
|
|
+> **日期**:2026-07-24
|
|
|
+> **项目**:`c260724`
|
|
|
+> **作者**:WanJL
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 一、多态(Polymorphism)
|
|
|
+
|
|
|
+### 1.1 什么是多态
|
|
|
+
|
|
|
+面向对象三大特征之一(封装、继承、多态)。
|
|
|
+**同一个对象,在不同时刻表现出来的不同形态。**
|
|
|
+
|
|
|
+例如:
|
|
|
+- 学生 `张三` 是 `Student` 类型
|
|
|
+- 若 `Student extends Person`,则张三同时具备 `Student` 和 `Person` 两种形态
|
|
|
+- 若 `Person extends Animal`,则张三具备 `Student`、`Person`、`Animal` 三种形态
|
|
|
+
|
|
|
+> **核心理解**:一个对象可以拥有多种类型身份,通过父类/接口的引用指向子类/实现类的对象。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 1.2 多态的前提条件
|
|
|
+
|
|
|
+| 条件 | 说明 |
|
|
|
+|------|------|
|
|
|
+| **① 继承或实现关系** | 子类 extends 父类,或实现类 implements 接口 |
|
|
|
+| **② 方法重写** | 子类/实现类必须重写父类/接口的方法 |
|
|
|
+| **③ 父类引用指向子类对象** | `Animal a = new Dog();` |
|
|
|
+
|
|
|
+```java
|
|
|
+// 父类引用指向子类对象
|
|
|
+Animal animal = new Dog();
|
|
|
+animal.eat();
|
|
|
+animal.sleep();
|
|
|
+```
|
|
|
+> 📄 来源:`Test01.java`
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 1.3 多态中成员的访问特点
|
|
|
+
|
|
|
+| 成员类型 | 编译时期 | 运行时期 |
|
|
|
+|----------|---------|---------|
|
|
|
+| **成员变量** | 看父类 | 看父类(没有多态) |
|
|
|
+| **成员方法** | 看父类(需存在) | 看子类(重写后执行子类) |
|
|
|
+
|
|
|
+**口诀**:编译看左边,运行看右边(针对方法而言)。
|
|
|
+
|
|
|
+```java
|
|
|
+// 仅能调用父类中声明的方法
|
|
|
+Animal animal = new Dog();
|
|
|
+animal.eat(); // ✅ 编译看父类有 eat(),运行执行 Dog 的 eat()
|
|
|
+animal.sleep(); // ✅ 编译看父类有 sleep()(抽象),运行执行 Dog 的 sleep()
|
|
|
+// animal.wangWang(); // ❌ 编译报错,父类没有 wangWang()
|
|
|
+```
|
|
|
+> 📄 来源:`Test01.java`、`Dog.java`
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 1.4 多态的好处——提高代码扩展性
|
|
|
+
|
|
|
+多态让代码对扩展开放,对修改关闭(开闭原则)。
|
|
|
+
|
|
|
+典型应用:**笔记本 USB 接口案例**
|
|
|
+
|
|
|
+```java
|
|
|
+// Usb 接口
|
|
|
+public interface Usb {
|
|
|
+ void startUsb();
|
|
|
+ void stopUsb();
|
|
|
+}
|
|
|
+
|
|
|
+// 笔记本类——接收任意 Usb 实现类
|
|
|
+public class NoteBook {
|
|
|
+ public void useUsb(Usb usb) { // 参数类型为 Usb 接口
|
|
|
+ usb.startUsb();
|
|
|
+ System.out.println("开始工作.....");
|
|
|
+ usb.stopUsb();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 鼠标实现 Usb
|
|
|
+public class Mouse implements Usb {
|
|
|
+ public void startUsb() { System.out.println("USB鼠标开启"); }
|
|
|
+ public void stopUsb() { System.out.println("USB鼠标关闭"); }
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Usb.java`、`NoteBook.java`、`Mouse.java`
|
|
|
+
|
|
|
+```java
|
|
|
+// 测试多态
|
|
|
+NoteBook noteBook = new NoteBook();
|
|
|
+Usb mouse = new Mouse();
|
|
|
+noteBook.useUsb(mouse); // ✅ 传入鼠标
|
|
|
+
|
|
|
+Usb cat = new Cat(); // ✅ 猫也能实现 Usb(示例演示)
|
|
|
+noteBook.useUsb(cat); // ✅ 传入猫 USB
|
|
|
+```
|
|
|
+> 📄 来源:`Test02.java`
|
|
|
+
|
|
|
+> **关键点**:`NoteBook.useUsb(Usb usb)` 的参数是接口类型,**任何实现 `Usb` 接口的类都可以传入**,无需修改笔记本代码即可扩展新设备。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、抽象类回顾与多态结合
|
|
|
+
|
|
|
+### 2.1 抽象类定义
|
|
|
+
|
|
|
+```java
|
|
|
+public abstract class Animal {
|
|
|
+ public void eat() { // 普通方法
|
|
|
+ System.out.println("动物吃饭.....");
|
|
|
+ }
|
|
|
+ public abstract void sleep(); // 抽象方法
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Animal.java`
|
|
|
+
|
|
|
+### 2.2 子类继承抽象类
|
|
|
+
|
|
|
+```java
|
|
|
+public class Dog extends Animal {
|
|
|
+ @Override
|
|
|
+ public void sleep() {
|
|
|
+ System.out.println("小狗睡觉....");
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ public void eat() {
|
|
|
+ System.out.println("小狗吃饭....");
|
|
|
+ }
|
|
|
+ public void wangWang() {
|
|
|
+ System.out.println("小狗汪汪....");
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Dog.java`
|
|
|
+
|
|
|
+- 子类必须重写父类的所有抽象方法(除非子类也是抽象类)
|
|
|
+- 子类可以重写父类的普通方法(`eat()`)
|
|
|
+- 子类可以扩展自己的特有方法(`wangWang()`)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、接口多态与接口新特性(JDK8+)
|
|
|
+
|
|
|
+### 3.1 接口定义
|
|
|
+
|
|
|
+```java
|
|
|
+public interface Usb {
|
|
|
+ void startUsb(); // 抽象方法(默认 public abstract)
|
|
|
+ void stopUsb();
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Usb.java`
|
|
|
+
|
|
|
+### 3.2 接口默认方法(JDK 8)
|
|
|
+
|
|
|
+在接口中定义带方法体的方法,使用 `default` 关键字。实现类可以选择重写或不重写。
|
|
|
+
|
|
|
+```java
|
|
|
+public interface Notifiable {
|
|
|
+ // 抽象方法——实现类必须重写
|
|
|
+ void doSend(String recipient, String message);
|
|
|
+
|
|
|
+ // 默认方法——校验参数(实现类可选重写)
|
|
|
+ default boolean validateParams(String recipient, String message) {
|
|
|
+ if (recipient != null && message != null && !recipient.isEmpty() && !message.isEmpty()) {
|
|
|
+ System.out.println("参数校验通过");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ System.out.println("参数校验失败:收件人或消息不能为空");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 默认方法——记录日志(实现类可选重写)
|
|
|
+ default void log(String level, String msg) {
|
|
|
+ System.out.println("[" + level + "]消息:" + msg);
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Notifiable.java`
|
|
|
+
|
|
|
+### 3.3 接口静态方法(JDK 8)
|
|
|
+
|
|
|
+使用 `static` 关键字定义,通过接口名直接调用。
|
|
|
+
|
|
|
+```java
|
|
|
+public interface Notifiable {
|
|
|
+ static void printNotificationType() {
|
|
|
+ System.out.println("通知系统 v1.0——支持邮件/短信/微信通知");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 调用方式
|
|
|
+Notifiable.printNotificationType();
|
|
|
+```
|
|
|
+> 📄 来源:`Notifiable.java`、`TestNotification.java`
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、模板方法设计模式(基于接口默认方法)
|
|
|
+
|
|
|
+在接口中定义一个 **默认方法** 作为模板,规定固定的算法流程,让实现类只需关注核心业务逻辑。
|
|
|
+
|
|
|
+```java
|
|
|
+public interface Notifiable {
|
|
|
+ // 模板方法——定义固定的发送流程
|
|
|
+ default void send(String recipient, String message) {
|
|
|
+ // 1、校验参数
|
|
|
+ boolean boo = validateParams(recipient, message);
|
|
|
+ if (boo) {
|
|
|
+ // 2、执行发送(调用抽象方法,由实现类完成具体逻辑)
|
|
|
+ doSend(recipient, message);
|
|
|
+ // 3、记录日志
|
|
|
+ log("INFO", "发送成功");
|
|
|
+ System.out.println("--- 发送流程结束 ---");
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Notifiable.java`
|
|
|
+
|
|
|
+**流程示意图**:
|
|
|
+```
|
|
|
+send() → validateParams() → doSend() → log() → 完成
|
|
|
+(模板) (默认方法-校验) (抽象方法) (默认方法)
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、课后作业:通知系统(Notifiable 体系)
|
|
|
+
|
|
|
+### 5.1 接口定义
|
|
|
+
|
|
|
+使用 JDK8 新特性定义通知接口:
|
|
|
+- 抽象方法 `doSend()`——实现类实现不同的发送逻辑
|
|
|
+- 默认方法 `validateParams()`——参数校验
|
|
|
+- 默认方法 `log()`——日志记录
|
|
|
+- 默认方法 `send()`——**模板方法**,组合流程
|
|
|
+- 静态方法 `printNotificationType()`——输出系统信息
|
|
|
+
|
|
|
+### 5.2 实现类
|
|
|
+
|
|
|
+```java
|
|
|
+public class EmailNotifier implements Notifiable {
|
|
|
+ @Override
|
|
|
+ public void doSend(String recipient, String message) {
|
|
|
+ System.out.println("发送邮件给 " + recipient + ":内容 -" + message);
|
|
|
+ }
|
|
|
+ // 可选重写默认方法 log()
|
|
|
+ @Override
|
|
|
+ public void log(String level, String msg) {
|
|
|
+ System.out.println("[邮件][" + level + "]消息:" + msg);
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`EmailNotifier.java`
|
|
|
+
|
|
|
+### 5.3 测试类
|
|
|
+
|
|
|
+```java
|
|
|
+public class TestNotification {
|
|
|
+ public static void main(String[] args) {
|
|
|
+ // 1、调用接口静态方法
|
|
|
+ Notifiable.printNotificationType();
|
|
|
+ // 2、创建实现类对象
|
|
|
+ EmailNotifier en = new EmailNotifier();
|
|
|
+ // 3、正常发送
|
|
|
+ en.send("admin@163.com", "系统升级通知");
|
|
|
+ // 4、参数为空——触发校验失败
|
|
|
+ en.send("", "测试");
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`TestNotification.java`
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、随堂练习要点
|
|
|
+
|
|
|
+| 练习方向 | 涉及知识点 | 对应文件 |
|
|
|
+|---------|-----------|---------|
|
|
|
+| 多态入门 | 多态前提、父类引用指向子类对象、成员访问特点 | `Test01.java`、`Dog.java` |
|
|
|
+| 接口多态 | Usb 接口、笔记本接入多设备 | `Test02.java`、`NoteBook.java` |
|
|
|
+| 通知系统(作业) | 接口默认方法、静态方法、模板方法设计模式 | 作业包 `homework` |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 七、拓展阅读 & 常见面试题
|
|
|
+
|
|
|
+1. **多态的实现原理**——Java 中多态是通过**动态绑定(后期绑定)**实现的,JVM 在运行时根据对象的实际类型调用对应的方法。
|
|
|
+2. **多态与继承的关系**——多态是基于继承或接口实现的。
|
|
|
+3. **多态的优势**——提高代码的可扩展性和可维护性,符合**开闭原则**(对扩展开放,对修改关闭)。
|
|
|
+4. **接口默认方法的用途**——在不破坏已有实现类的前提下向接口添加新方法;实现模板方法模式。
|
|
|
+5. **接口静态方法的用途**——提供工具方法,接口即命名空间,无需额外工具类。
|
|
|
+6. **模板方法设计模式**——定义一个操作中的算法骨架(模板方法),将一些步骤延迟到子类/实现类中实现。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 八、今日知识图谱
|
|
|
+
|
|
|
+```
|
|
|
+面向对象三大特征
|
|
|
+├── 封装(private / getter / setter)
|
|
|
+├── 继承(extends / super / @Override)
|
|
|
+└── 多态 ⭐(今日重点)
|
|
|
+ ├── 前提:继承/实现 + 重写 + 父类引用指向子类对象
|
|
|
+ ├── 成员访问:编译看左边,运行看右边
|
|
|
+ ├── 多态的好处:提高扩展性(开闭原则)
|
|
|
+ │ └── 案例:NoteBook.useUsb(Usb usb)
|
|
|
+ └── 接口多态 + JDK8 新特性
|
|
|
+ ├── 默认方法(default)—— 模板方法设计模式
|
|
|
+ └── 静态方法(static)—— 接口名直接调用
|
|
|
+```
|