2026年7月24日-作业.md 20 KB

2026-07-24 JavaSE 课后作业

课程内容:多态(Polymorphism)、多态中的转型(向上转型/向下转型)、instanceof 运算符、抽象类与多态结合、接口多态案例(USB + 笔记本)、内部类(成员内部类/静态成员内部类/局部内部类)

涉及前序知识:继承、抽象类、接口、封装、构造方法、方法重写

提交方式:在 提交\姓名\ 目录下创建对应的 Java 源文件

截止时间:下次上课前


📌 本次作业重要说明

命名要求

项目 要求
包名 必须按题目指定的包名创建(全小写)
类名 自由命名,但需见名知意
测试类 建议命名为 TestXxxXxxTest
文件名 必须与类名一致

提交目录结构示例

提交\
└─ 张三\
    ├─ p1_smarthome\             ← 第 1 题的包
    │   ├─ SmartDevice.java        ← 接口
    │   ├─ Light.java              ← 实现类(特有:调色)
    │   ├─ AirConditioner.java     ← 实现类(特有:定时)
    │   ├─ RobotVacuum.java        ← 实现类(特有:清洁模式)
    │   └─ SmartHomeController.java ← 测试类(多态 + instanceof)
    ├─ p2_myarray\               ← 第 2 题的包
    │   └─ MyArray.java + MyArrayTest.java
    └─ p3_exam\                  ← 第 3 题的包
        ├─ ExamTemplate.java       ← 抽象类(模板方法)
        ├─ JavaExam.java           ← 子类
        ├─ MathExam.java           ← 子类
        └─ ExamTest.java           ← 测试类

注意:包名必须严格按题目要求书写(全小写),目录结构必须与包结构一致。


第 1 题:接口多态 + 转型 + instanceof——智能家居控制系统 ⭐⭐⭐

包名p1_smarthome

知识点:接口定义与实现、接口多态(参数/数组)、向上转型、向下转型、instanceof 运算符、调用实现类特有方法、开闭原则

需求说明

开发一个智能家居控制系统。不同家电的开关方式和运行逻辑不同,但都遵循统一的控制规范:打开 → 运行 → 关闭。此外,每种家电还有各自的特有功能(灯可以调色、空调可以定时、扫地机器人有不同清洁模式)。

请使用 接口多态 + instanceof + 向下转型 来设计,要求:

  • 控制器通过接口类型操作所有设备(多态)
  • 通过 instanceof 判断设备类型后向下转型,调用特有功能

接口设计

SmartDevice 接口

方法 说明
void turnOn() 打开设备
void doWork() 执行工作
void turnOff() 关闭设备

实现类要求

Light 类(灯——实现 SmartDevice)

成员 说明
私有属性 location(位置,String,如 "客厅" / "卧室")
构造方法 Light(String location)
实现 turnOn() 输出 "xxx 的灯已打开"
实现 doWork() 输出 "xxx 的灯照明中..."
实现 turnOff() 输出 "xxx 的灯已关闭"
特有方法 void changeColor(String color) —— 输出 "xxx 的灯光变为 xxx 色"

AirConditioner 类(空调——实现 SmartDevice)

成员 说明
私有属性 roomName(房间名,String)、temperature(温度,int)
构造方法 AirConditioner(String roomName, int temperature)
实现 turnOn() 输出 "xxx 空调已打开,设定温度:xxx℃"
实现 doWork() 输出 "xxx 空调制冷中,当前室温正降至 xxx℃..."
实现 turnOff() 输出 "xxx 空调已关闭"
特有方法 void setTimer(int hours) —— 输出 "xxx 空调已设置 xxx 小时后自动关闭"

RobotVacuum 类(扫地机器人——实现 SmartDevice)

成员 说明
私有属性 model(型号,String)、batteryLevel(电量,int,百分比)
构造方法 RobotVacuum(String model, int batteryLevel)
实现 turnOn() 输出 "扫地机器人 xxx 已启动,当前电量:xxx%"
实现 doWork() 输出 "扫地机器人 xxx 开始清扫地面..."
实现 turnOff() 输出 "扫地机器人 xxx 已完成清扫,自动关闭"
特有方法 void startCleaningMode(String mode) —— 输出 "扫地机器人 xxx 已切换到 xxx 模式开始清扫"(mode 如 "强力" / "静音" / "边缘")

测试类要求

SmartHomeController(测试类,含 main 方法):

  1. 创建设备数组:创建一个 SmartDevice[] 数组,包含至少 5 个设备

    SmartDevice light1 = new Light("客厅");
    SmartDevice ac = new AirConditioner("主卧", 26);
    SmartDevice robot = new RobotVacuum("石头T10", 80);
    SmartDevice light2 = new Light("书房");
    SmartDevice ac2 = new AirConditioner("次卧", 24);
    
  2. 遍历数组,执行通用工作流程:对每个设备依次调用 turnOn()doWork()turnOff()

  3. 遍历数组,执行特有功能:使用 instanceof 判断设备类型后向下转型,调用特有方法:

    • 如果是 Light → 向下转型 → 调用 changeColor("暖黄")
    • 如果是 AirConditioner → 向下转型 → 调用 setTimer(4)(4 小时)
    • 如果是 RobotVacuum → 向下转型 → 调用 startCleaningMode("强力")
  4. 编写静态方法 startDevice(SmartDevice device, int seconds)

    • 调用 device.turnOn()
    • 输出 "设备工作中,请等待" + seconds + "秒..."
    • 调用 device.doWork()
    • 使用 instanceof 判断类型后向下转型,调用特有方法(与第 3 步逻辑相同)
    • 调用 device.turnOff()
    • main 中传入不同类型设备调用此方法

思考题

  1. 方法参数 SmartDevice device 能传入哪些类型的对象?调用 device.changeColor() 行吗?为什么?
  2. 如果新增一个 SmartSpeaker(智能音箱)实现 SmartDeviceSmartHomeController 需要修改哪些代码?是否符合"开闭原则"?
  3. 如果将 SmartDevice 改为抽象类而不是接口,设计上会有什么不同?还能实现"一个类实现多个规范"吗?

预期输出

========== 智能家居启动 ==========
客厅的灯已打开
客厅的灯照明中...
客厅的灯已关闭
客厅的灯光变为暖黄色

主卧空调已打开,设定温度:26℃
主卧空调制冷中,当前室温正降至 26℃...
主卧空调已关闭
主卧空调已设置 4 小时后自动关闭

扫地机器人 石头T10 已启动,当前电量:80%
扫地机器人 石头T10 开始清扫地面...
扫地机器人 石头T10 已完成清扫,自动关闭
扫地机器人 石头T10 已切换到 强力 模式开始清扫

书房的灯已打开
书房的灯照明中...
书房的灯已关闭
书房的灯光变为暖黄色

次卧空调已打开,设定温度:24℃
次卧空调制冷中,当前室温正降至 24℃...
次卧空调已关闭
次卧空调已设置 4 小时后自动关闭

========== 测试 startDevice 方法 ==========
客厅的灯已打开
设备工作中,请等待10秒...
客厅的灯照明中...
客厅的灯光变为暖黄色
客厅的灯已关闭

提示

  • main 中调用 startDevice 时,可以直接传入数组中的元素,如 controller.startDevice(devices[0], 10);
  • instanceof 判断的是运行时类型,不是编译时类型
  • 特有方法只能通过向下转型后的子类引用调用,父类/接口引用无法直接调用

需求说明

开发一个智能家居控制系统。不同家电的开关方式和运行逻辑不同,但都遵循统一的控制规范:打开 → 运行 → 关闭

请使用 接口多态 来设计,要求控制器不依赖具体家电类型。

类设计

SmartDevice 接口

方法 说明
void turnOn() 打开设备
void doWork() 执行工作
void turnOff() 关闭设备

Light 类(灯——实现 SmartDevice)

成员 说明
私有属性 location(位置,String,如 "客厅" / "卧室")
构造方法 Light(String location)
实现 turnOn() 输出 "xxx 的灯已打开"
实现 doWork() 输出 "xxx 的灯照明中..."
实现 turnOff() 输出 "xxx 的灯已关闭"

AirConditioner 类(空调——实现 SmartDevice)

成员 说明
私有属性 roomName(房间名,String)、temperature(温度,int)
构造方法 AirConditioner(String roomName, int temperature)
实现 turnOn() 输出 "xxx 空调已打开,设定温度:xxx℃"
实现 doWork() 输出 "xxx 空调制冷中,当前室温正降至 xxx℃..."
实现 turnOff() 输出 "xxx 空调已关闭"

RobotVacuum 类(扫地机器人——实现 SmartDevice)

成员 说明
私有属性 model(型号,String)、batteryLevel(电量,int,百分比)
构造方法 RobotVacuum(String model, int batteryLevel)
实现 turnOn() 输出 "扫地机器人 xxx 已启动,当前电量:xxx%"
实现 doWork() 输出 "扫地机器人 xxx 开始清扫地面..."
实现 turnOff() 输出 "扫地机器人 xxx 已完成清扫,自动关闭"

测试类要求

SmartHomeController

  1. 创建设备数组SmartDevice[] 数组,包含至少 4 个设备

    SmartDevice light1 = new Light("客厅");
    SmartDevice ac = new AirConditioner("主卧", 26);
    SmartDevice robot = new RobotVacuum("石头T10", 80);
    SmartDevice light2 = new Light("书房");
    
  2. 遍历执行工作流程:对每个设备依次调用 turnOn()doWork()turnOff()

  3. 编写静态方法 startDevice(SmartDevice device, int seconds)

    • 调用 device.turnOn()
    • 输出 "设备工作中,请等待" + seconds + "秒..."
    • 调用 device.doWork()
    • 调用 device.turnOff()
    • main 中用不同类型设备调用该方法

思考题

  1. 方法参数 SmartDevice device 可以传入哪些类型的对象?这体现了多态的什么好处?
  2. 如果新增 SmartSpeaker 实现 SmartDevice,控制器需要修改吗?
  3. 对比课堂 NoteBook.useUsb(Usb usb) 案例,设计思路有什么相似之处?

预期输出

========== 智能家居启动 ==========
客厅的灯已打开
客厅的灯照明中...
客厅的灯已关闭

主卧空调已打开,设定温度:26℃
主卧空调制冷中,当前室温正降至 26℃...
主卧空调已关闭

扫地机器人 石头T10 已启动,当前电量:80%
扫地机器人 石头T10 开始清扫地面...
扫地机器人 石头T10 已完成清扫,自动关闭

书房的灯已打开
书房的灯照明中...
书房的灯已关闭

========== 测试 startDevice 方法 ==========
客厅的灯已打开
设备工作中,请等待10秒...
客厅的灯照明中...
客厅的灯已关闭

第 2 题:综合大挑战——MyArray 可变数组(动态数组底层实现)⭐⭐⭐⭐⭐

包名p2_myarray

知识点:构造方法、数组扩容、方法封装、增删改查、元素前移、冒泡排序

模仿 ArrayList 的底层原理,自己动手实现一个可变数组(动态数组)。

需求背景

Java 中普通数组 int[] 一旦创建,长度就固定了,无法动态增减元素。请自行实现一个 可变整型数组 MyArray 类,内部使用 int[] 存储数据,对外提供便捷的增删改查方法。

实体类说明:MyArray

私有属性

属性 类型 说明
data int[] 内部真正存储数据的数组
size int 当前已存储的元素个数(不是数组长度)

构造方法

构造方法 说明
MyArray() 无参构造,默认初始化容量为 10 的数组
MyArray(int capacity) 指定初始容量,如果传入的容量 ≤ 0,则使用默认容量 10

核心方法列表(共 11 个)

1. 添加元素 — add(int element)

  • 如果内部数组已满,自动扩容为当前容量的 1.5 倍data.length * 3 / 2
  • 扩容步骤:创建新数组 → 复制旧元素 → 替换 data 引用
  • 将新元素存入 data[size]size 自增 1

2. 获取元素 — get(int index)

  • 下标越界时输出 "下标越界,无法获取元素",返回 -1
  • 否则返回 data[index]

3. 修改元素 — set(int index, int element)

  • 下标越界时输出 "下标越界,无法修改元素"
  • 否则将 data[index] 赋值为 element

4. 获取长度 — size()

  • 返回 size 属性值

5. 获取容量 — capacity()

  • 返回 data.length

6. 判断是否为空 — isEmpty()

  • size == 0 返回 true,否则 false

7. 查找元素下标 — indexOf(int element)

  • 从前向后遍历,找到第一个匹配的元素下标,没找到返回 -1

8. 判断是否包含 — contains(int element)

  • 调用 indexOf(),根据返回值是否为 -1 判断

9. 删除指定位置的元素 — remove(int index)

  • 下标越界时输出 "下标越界,无法删除元素",返回 -1
  • 否则:保存被删除的值 → 后面元素前移一位 → size-- → 返回被删除的值

10. 删除指定值的元素 — removeByValue(int element)

  • 调用 indexOf() 获取下标
  • 下标为 -1 则输出 "未找到该元素,删除失败",返回 false
  • 否则调用 remove(index),返回 true

11. 数组排序 — sort(boolean ascending)

  • true 升序,false 降序
  • 使用冒泡排序,只对 data[0] ~ data[size-1] 排序

辅助方法

print()

  • 遍历输出格式:[元素1, 元素2, 元素3, ...]
  • 空数组输出 []

clear()

  • size 置为 0(内部数组保留)

测试类要求

MyArrayTest

public class MyArrayTest {
    public static void main(String[] args) {
        // 1. 创建一个初始容量为 3 的 MyArray 对象
        MyArray arr = new MyArray(3);

        // 2. 输出初始状态
        System.out.println("初始容量:" + arr.capacity());   // 3
        System.out.println("是否为空:" + arr.isEmpty());     // true

        // 3. 添加 5 个元素(触发自动扩容)
        for (int i = 1; i <= 5; i++) {
            arr.add(i * 10);  // 添加 10, 20, 30, 40, 50
        }
        arr.print();           // [10, 20, 30, 40, 50]

        // 4. 测试各个方法
        System.out.println("元素个数:" + arr.size());        // 5
        System.out.println("当前容量:" + arr.capacity());     // 6
        System.out.println("下标2的元素:" + arr.get(2));     // 30
        System.out.println("是否包含40:" + arr.contains(40)); // true
        System.out.println("50的下标:" + arr.indexOf(50));   // 4

        // 5. 测试修改
        arr.set(1, 99);
        arr.print();           // [10, 99, 30, 40, 50]

        // 6. 测试删除
        int deleted = arr.remove(2);
        System.out.println("被删除的元素:" + deleted);       // 30
        arr.print();           // [10, 99, 40, 50]

        // 7. 测试按值删除
        arr.removeByValue(10);
        arr.print();           // [99, 40, 50]

        // 8. 测试升序排序
        arr.sort(true);
        arr.print();           // [40, 50, 99]

        // 9. 测试降序排序
        arr.sort(false);
        arr.print();           // [99, 50, 40]

        // 10. 测试越界访问
        System.out.println(arr.get(10));  // 下标越界,无法获取元素 → -1
        arr.remove(10);                   // 下标越界,无法删除元素 → -1
    }
}

思考题

  1. 如果 add() 方法中每次只扩容 1 个容量(data.length + 1),当添加大量元素时性能会怎样?为什么选择 1.5 倍?
  2. remove() 方法中为什么要将后面的元素向前移动?如果删除的是最后一个元素还需要移动吗?
  3. 如何将 MyArray 改造为支持任意类型的 MyArrayList<T>

第 3 题:模板方法设计模式——在线考试系统 ⭐⭐⭐⭐⭐

包名p3_exam

知识点:抽象类、抽象方法、模板方法(final)、方法重写、继承

模板方法模式(Template Method Pattern)是抽象类的经典应用场景。父类定义算法的「骨架」,子类实现特定的「步骤」

需求说明

模拟一个「在线考试系统」,每门考试都需要经过以下步骤:

  1. 登录验证(所有考试相同)
  2. 发放试卷(所有考试相同)
  3. 考试进行中(不同科目考试内容不同)← 抽象方法
  4. 收卷评分(不同科目评分标准不同)← 抽象方法
  5. 公布成绩(所有考试相同)

类设计

ExamTemplate 抽象类(父类):

  • 普通方法 login() —— 输出 "考生登录系统,验证身份... 登录成功!"
  • 普通方法 deliverPaper() —— 输出 "发放试卷,考试开始!"
  • 抽象方法 void conductExam() —— 考试进行中(不同科目不同)
  • 抽象方法 void gradeExam() —— 收卷评分(不同科目不同)
  • 普通方法 announceResult() —— 输出 "成绩公布!请登录系统查看"
  • 模板方法 final void startExam() —— 按顺序执行完整考试流程:
    1. 调用 login()
    2. 调用 deliverPaper()
    3. 调用 conductExam()
    4. 调用 gradeExam()
    5. 调用 announceResult()

JavaExam(继承 ExamTemplate):

  • 重写 conductExam() —— 输出 "Java 考试进行中:编写代码,回答选择题..."
  • 重写 gradeExam() —— 输出 "Java 考试评分:检查代码正确性,选择题自动判分..."

MathExam(继承 ExamTemplate):

  • 重写 conductExam() —— 输出 "数学考试进行中:解答微积分、线性代数题目..."
  • 重写 gradeExam() —— 输出 "数学考试评分:答案比对,步骤给分..."

测试类要求

ExamTest

  1. 创建 JavaExam 对象,调用 startExam() 方法
  2. 创建 MathExam 对象,调用 startExam() 方法
  3. 观察:考试流程的「骨架」由父类定义,子类只需实现「考试内容」和「评分方式」两个步骤

预期输出

========== Java 考试 ==========
考生登录系统,验证身份... 登录成功!
发放试卷,考试开始!
Java 考试进行中:编写代码,回答选择题...
Java 考试评分:检查代码正确性,选择题自动判分...
成绩公布!请登录系统查看

========== 数学考试 ==========
考生登录系统,验证身份... 登录成功!
发放试卷,考试开始!
数学考试进行中:解答微积分、线性代数题目...
数学考试评分:答案比对,步骤给分...
成绩公布!请登录系统查看

思考题

  1. startExam() 方法为什么用 final 修饰?如果不加 final 会怎样?
  2. 模板方法模式的核心思想是什么?和「普通继承 + 方法重写」有什么区别?
  3. 你在日常生活中有哪些场景可以用模板方法模式来描述?(例如:做饭流程、工作日报提交流程等)

📋 题目总览

题号 名称 核心知识点 难度
第 1 题 智能家居控制系统 接口多态、向上转型/向下转型、instanceof、调用实现类特有方法、开闭原则 ⭐⭐⭐
第 2 题 MyArray 可变数组 构造方法、数组扩容、增删改查、元素前移、冒泡排序 ⭐⭐⭐⭐⭐
第 3 题 在线考试系统(模板方法) 抽象类、模板方法、final、方法重写 ⭐⭐⭐⭐⭐