|
|
@@ -0,0 +1,225 @@
|
|
|
+# 2026-07-23 JavaSE 课后作业
|
|
|
+
|
|
|
+> **课程内容**:抽象类(abstract)、final 关键字、模板方法设计模式、代码块(局部/构造/静态)、接口(Interface)、接口 JDK8+ 新特性(默认方法/静态方法/私有方法)
|
|
|
+>
|
|
|
+> **涉及前序知识**:继承、构造方法、方法重写、多态、封装
|
|
|
+>
|
|
|
+> **提交方式**:在 `提交\姓名\` 目录下创建对应的 Java 源文件
|
|
|
+>
|
|
|
+> **截止时间**:下次上课前
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 📌 本次作业重要说明
|
|
|
+
|
|
|
+### 命名要求
|
|
|
+
|
|
|
+| 项目 | 要求 |
|
|
|
+|------|------|
|
|
|
+| **包名** | **必须按题目指定的包名创建**(全小写) |
|
|
|
+| **类名** | 自由命名,但需**见名知意**(如实体类用 `Printer`、`EmailNotifier` 等均可) |
|
|
|
+| **测试类** | 建议命名为 `TestXxx` 或 `XxxTest` |
|
|
|
+| **文件名** | 必须与类名一致 |
|
|
|
+
|
|
|
+### 提交目录结构示例
|
|
|
+
|
|
|
+```
|
|
|
+提交\
|
|
|
+└─ 张三\
|
|
|
+ ├─ p1_printer\ ← 第 1 题的包
|
|
|
+ │ ├─ Printer.java ← 抽象父类
|
|
|
+ │ ├─ Connectable.java ← 接口
|
|
|
+ │ ├─ LaserPrinter.java ← 子类(继承 + 实现)
|
|
|
+ │ ├─ InkjetPrinter.java ← 子类(继承 + 实现)
|
|
|
+ │ └─ TestPrinter.java ← 测试类
|
|
|
+ └─ p2_notification\ ← 第 2 题的包
|
|
|
+ ├─ Notifiable.java ← 接口(含默认方法)
|
|
|
+ ├─ EmailNotifier.java ← 实现类
|
|
|
+ ├─ SMSNotifier.java ← 实现类
|
|
|
+ └─ TestNotification.java ← 测试类
|
|
|
+```
|
|
|
+
|
|
|
+> ⚠ **注意**:包名必须严格按题目要求书写(全小写),目录结构必须与包结构一致。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第 1 题:抽象类 + 接口——Printer 打印机体系 ⭐⭐
|
|
|
+
|
|
|
+**包名**:`p1_printer`
|
|
|
+
|
|
|
+**知识点**:抽象类定义与使用、接口定义与实现、类同时继承抽象类并实现接口、方法重写、多态
|
|
|
+
|
|
|
+### 需求说明
|
|
|
+
|
|
|
+某公司需要开发一个打印机管理系统。不同类型的打印机有 **共有的属性**(品牌、型号),也有 **共同的连接规范**(连接、打印、关闭)。请使用 **抽象类 + 接口** 来设计这个体系。
|
|
|
+
|
|
|
+### 类设计
|
|
|
+
|
|
|
+#### Connectable 接口
|
|
|
+- **抽象方法**:`void connect()` —— 连接设备
|
|
|
+- **抽象方法**:`void print(String content)` —— 执行打印(参数为待打印内容)
|
|
|
+- **抽象方法**:`void close()` —— 关闭设备
|
|
|
+
|
|
|
+#### Printer 抽象类
|
|
|
+- **私有属性**:`brand`(品牌,String)、`model`(型号,String)
|
|
|
+- **有参构造方法**:`Printer(String brand, String model)`
|
|
|
+- **getter/setter**
|
|
|
+- **普通方法**:`showInfo()` —— 输出 `"打印机:xxx 品牌:xxx"`(xxx 为型号和品牌)
|
|
|
+- **抽象方法**:`void maintenance()` —— 维护保养(不同打印机保养方式不同)
|
|
|
+
|
|
|
+#### LaserPrinter 类(激光打印机)
|
|
|
+- **继承** `Printer` 抽象类,**实现** `Connectable` 接口
|
|
|
+- **新增私有属性**:`tonerLevel`(碳粉余量,int,百分比 0~100)
|
|
|
+- **构造方法**:`LaserPrinter(String brand, String model, int tonerLevel)`
|
|
|
+- **实现** `connect()` —— 输出 `"激光打印机已连接"`
|
|
|
+- **实现** `print(String content)` —— 输出 `"激光打印机打印:xxx"`(xxx 为 content)
|
|
|
+- **实现** `close()` —— 输出 `"激光打印机已关闭"`
|
|
|
+- **重写** `maintenance()` —— 输出 `"激光打印机保养:检查碳粉,当前余量:xxx%"`
|
|
|
+
|
|
|
+#### InkjetPrinter 类(喷墨打印机)
|
|
|
+- **继承** `Printer` 抽象类,**实现** `Connectable` 接口
|
|
|
+- **新增私有属性**:`inkLevel`(墨水余量,int,百分比 0~100)
|
|
|
+- **构造方法**:`InkjetPrinter(String brand, String model, int inkLevel)`
|
|
|
+- **实现** `connect()` —— 输出 `"喷墨打印机已连接"`
|
|
|
+- **实现** `print(String content)` —— 输出 `"喷墨打印机打印:xxx"`
|
|
|
+- **实现** `close()` —— 输出 `"喷墨打印机已关闭"`
|
|
|
+- **重写** `maintenance()` —— 输出 `"喷墨打印机保养:检查墨水,当前余量:xxx%"`
|
|
|
+
|
|
|
+### 测试类要求
|
|
|
+
|
|
|
+**`TestPrinter` 类**(置于 `p1_printer` 包下):
|
|
|
+
|
|
|
+1. 创建 `LaserPrinter` 对象(品牌:"惠普",型号:"HP1010",碳粉余量:80)
|
|
|
+2. 创建 `InkjetPrinter` 对象(品牌:"爱普生",型号:"L3153",墨水余量:60)
|
|
|
+3. 调用每个对象的 `showInfo()` 方法
|
|
|
+4. 调用每个对象的 `connect()` → `print("Hello World")` → `close()` 三步操作
|
|
|
+5. 调用每个对象的 `maintenance()` 方法
|
|
|
+
|
|
|
+### 思考题(不需编码,口头回答)
|
|
|
+
|
|
|
+1. 如果把 `Connectable` 改为抽象类,让 `LaserPrinter` 直接继承它,会出现什么问题?(提示:Java 的单继承限制)
|
|
|
+2. `Printer` 中使用抽象方法 `maintenance()` 的好处是什么?能否用普通方法代替?
|
|
|
+3. `showInfo()` 方法是在抽象类中定义的普通方法,它在测试时表现出了什么特性?
|
|
|
+
|
|
|
+### 预期输出
|
|
|
+
|
|
|
+```
|
|
|
+========== 激光打印机 ==========
|
|
|
+打印机:HP1010 品牌:惠普
|
|
|
+激光打印机已连接
|
|
|
+激光打印机打印:Hello World
|
|
|
+激光打印机已关闭
|
|
|
+激光打印机保养:检查碳粉,当前余量:80%
|
|
|
+
|
|
|
+========== 喷墨打印机 ==========
|
|
|
+打印机:L3153 品牌:爱普生
|
|
|
+喷墨打印机已连接
|
|
|
+喷墨打印机打印:Hello World
|
|
|
+喷墨打印机已关闭
|
|
|
+喷墨打印机保养:检查墨水,当前余量:60%
|
|
|
+```
|
|
|
+
|
|
|
+> 💡 **提示**:
|
|
|
+> - 子类构造方法中要调用 `super(brand, model)` 初始化父类属性
|
|
|
+> - 实现接口时使用 `implements` 关键字,继承抽象类时使用 `extends` 关键字,两者用逗号分隔:`extends Printer implements Connectable`
|
|
|
+> - 抽象类 Printer 中的 `maintenance()` 和接口 Connectable 中的三个方法 **都需要重写**
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第 2 题:接口 + JDK8 默认方法——Notification 通知体系 ⭐⭐⭐
|
|
|
+
|
|
|
+**包名**:`p2_notification`
|
|
|
+
|
|
|
+**知识点**:接口定义、接口 JDK8 默认方法(default)、接口 JDK8 静态方法(static)、实现类重写抽象方法、通过接口名调用静态方法
|
|
|
+
|
|
|
+### 需求说明
|
|
|
+
|
|
|
+某系统需要发送多种类型的通知(邮件、短信、微信)。每种通知的 **发送逻辑不同**,但 **发送前需要校验参数**、**发送后需要记录日志**,这部分是公共行为。请使用 **接口 + JDK8 默认方法** 来设计。
|
|
|
+
|
|
|
+### 接口设计
|
|
|
+
|
|
|
+#### Notifiable 接口
|
|
|
+
|
|
|
+**抽象方法**(实现类必须重写):
|
|
|
+- `void doSend(String recipient, String message)` —— 执行具体的发送逻辑
|
|
|
+
|
|
|
+**默认方法**(JDK8,不强制重写,实现类可直接继承使用):
|
|
|
+- `default boolean validateParams(String recipient, String message)` —— 校验参数
|
|
|
+ - 如果 `recipient` 或 `message` 为 `null` 或空字符串,输出 `"参数校验失败:收件人或消息不能为空"`,返回 `false`
|
|
|
+ - 否则输出 `"参数校验通过"`,返回 `true`
|
|
|
+
|
|
|
+- `default void log(String level, String msg)` —— 记录日志
|
|
|
+ - 输出 `"[等级] 消息:内容"`(例如:`"[INFO] 消息:邮件发送成功"`)
|
|
|
+
|
|
|
+- `default void send(String recipient, String message)` —— **模板方法**(`final` 不能用在接口方法中,所以此处用 default 模拟)
|
|
|
+ - 步骤①:调用 `validateParams(recipient, message)` 校验参数,如果返回 `false` 则直接结束
|
|
|
+ - 步骤②:调用 `doSend(recipient, message)` 执行具体发送
|
|
|
+ - 步骤③:调用 `log("INFO", "发送成功")` 记录日志
|
|
|
+ - 步骤④:输出 `"--- 发送流程结束 ---"`
|
|
|
+
|
|
|
+**静态方法**(JDK8,通过 `接口名.方法名()` 调用):
|
|
|
+- `static void printNotificationType()` —— 输出 `"通知系统 v1.0——支持邮件/短信/微信通知"`
|
|
|
+
|
|
|
+### 实现类要求
|
|
|
+
|
|
|
+#### EmailNotifier 类(实现 Notifiable)
|
|
|
+- **实现** `doSend(String recipient, String message)` —— 输出 `"发送邮件给 xxx:内容 - yyy"`(xxx 为 recipient,yyy 为 message)
|
|
|
+- **可选重写** `log(String level, String msg)` —— 输出 `"[邮件][等级] 消息:内容"`
|
|
|
+
|
|
|
+#### SMSNotifier 类(实现 Notifiable)
|
|
|
+- **实现** `doSend(String recipient, String message)` —— 输出 `"发送短信给 xxx:内容 - yyy"`
|
|
|
+- 默认方法 `log()` 和 `validateParams()` **不重写**,直接继承接口的默认实现
|
|
|
+
|
|
|
+### 测试类要求
|
|
|
+
|
|
|
+**`TestNotification` 类**(置于 `p2_notification` 包下):
|
|
|
+
|
|
|
+1. 调用 `Notifiable.printNotificationType()` 输出系统信息(静态方法调用)
|
|
|
+2. 创建 `EmailNotifier` 对象,分别测试:
|
|
|
+ - 调用 `send("admin@example.com", "系统升级通知")` —— 正常发送
|
|
|
+ - 调用 `send("", "测试")` —— 参数为空,应校验失败
|
|
|
+3. 创建 `SMSNotifier` 对象,测试:
|
|
|
+ - 调用 `send("13800138000", "您的验证码是1234")` —— 正常发送
|
|
|
+
|
|
|
+### 思考题(不需编码,口头回答)
|
|
|
+
|
|
|
+1. 接口中的 `send()` 方法为什么不能像模板方法模式一样用 `final` 修饰?如果想让子类不能修改发送流程,有什么替代方案?
|
|
|
+2. `EmailNotifier` 重写了 `log()` 方法,而 `SMSNotifier` 没有重写。测试时两者的日志输出有什么不同?这体现了接口默认方法的什么特性?
|
|
|
+3. 接口中的静态方法 `printNotificationType()` 能否通过实现类对象调用?为什么?
|
|
|
+
|
|
|
+### 预期输出
|
|
|
+
|
|
|
+```
|
|
|
+通知系统 v1.0——支持邮件/短信/微信通知
|
|
|
+
|
|
|
+========== 邮件通知(正常) ==========
|
|
|
+参数校验通过
|
|
|
+发送邮件给 admin@example.com:内容 - 系统升级通知
|
|
|
+[邮件][INFO] 消息:发送成功
|
|
|
+--- 发送流程结束 ---
|
|
|
+
|
|
|
+========== 邮件通知(参数为空) ==========
|
|
|
+参数校验失败:收件人或消息不能为空
|
|
|
+
|
|
|
+========== 短信通知 ==========
|
|
|
+参数校验通过
|
|
|
+发送短信给 13800138000:内容 - 您的验证码是1234
|
|
|
+[INFO] 消息:发送成功
|
|
|
+--- 发送流程结束 ---
|
|
|
+```
|
|
|
+
|
|
|
+> 💡 **提示**:
|
|
|
+> - 接口中的方法默认是 `public`,实现类重写时也必须用 `public`
|
|
|
+> - 默认方法用 `default` 关键字修饰,可以有方法体
|
|
|
+> - 静态方法用 `static` 修饰,必须通过 `接口名.静态方法名()` 调用
|
|
|
+> - 默认方法和静态方法都是 JDK8 新增的特性
|
|
|
+> - `String` 类型判断空或空字符串:`recipient == null || recipient.isEmpty()`
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 📋 题目总览
|
|
|
+
|
|
|
+| 序号 | 包名 | 核心知识点 | 难度 |
|
|
|
+|------|------|-----------|------|
|
|
|
+| 第 1 题 | `p1_printer` | 抽象类定义与使用、接口定义与实现、类同时继承抽象类并实现接口、方法重写 | ⭐⭐ |
|
|
|
+| 第 2 题 | `p2_notification` | 接口定义、JDK8 默认方法(default)、JDK8 静态方法(static)、模拟模板方法、方法重写 vs 默认继承 | ⭐⭐⭐ |
|