# 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)—— 接口名直接调用 ```