|
|
@@ -0,0 +1,467 @@
|
|
|
+# JavaSE 基础 — Day08 笔记
|
|
|
+
|
|
|
+> **日期**:2026-07-22
|
|
|
+> **项目**:`c260722`
|
|
|
+> **作者**:WanJL
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 一、继承(Inheritance)
|
|
|
+
|
|
|
+### 1. 继承的概念
|
|
|
+
|
|
|
+**文件**:`Demo01.java`
|
|
|
+
|
|
|
+继承是 Java 三大特征之一(封装、继承、多态)。继承可以让**子类**具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法。
|
|
|
+
|
|
|
+继承的关键字是 `extends`,直译是「扩展」,含义是子类在父类的基础上进行扩展。
|
|
|
+
|
|
|
+**核心思想**:
|
|
|
+- 子类具有父类的特征
|
|
|
+- 父类是根据多个具有相同特征的子类所抽取出来的公共部分
|
|
|
+
|
|
|
+**类的层次结构示例**:
|
|
|
+```
|
|
|
+动物 类
|
|
|
+ |- 哺乳动物 类
|
|
|
+ |- 猫科动物 类
|
|
|
+ |- 猫 类
|
|
|
+ |- 狮子 类
|
|
|
+ |- 老虎 类
|
|
|
+ |- 犬科动物 类
|
|
|
+ |- 狼 类
|
|
|
+ |- 狗 类
|
|
|
+ |- 爬行动物 类
|
|
|
+ |- 两栖动物 类
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 继承的格式
|
|
|
+
|
|
|
+**文件**:`Demo01.java`
|
|
|
+
|
|
|
+```java
|
|
|
+class 子类 extends 父类 {
|
|
|
+ // 子类自己的成员
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**示例**:
|
|
|
+```java
|
|
|
+class Animal { // 父类
|
|
|
+}
|
|
|
+
|
|
|
+class Bird extends Animal { // 子类 Bird 继承 Animal
|
|
|
+}
|
|
|
+
|
|
|
+class Penguin extends Bird { // 子类 Penguin 继承 Bird(多层继承)
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 继承体系示例
|
|
|
+
|
|
|
+**文件**:`Animal.java`、`Bird.java`、`Penguin.java`
|
|
|
+
|
|
|
+```java
|
|
|
+// 父类 Animal —— 定义所有动物共有的行为
|
|
|
+public class Animal {
|
|
|
+ public void eat() {
|
|
|
+ System.out.println("吃......");
|
|
|
+ }
|
|
|
+ public void sleep() {
|
|
|
+ System.out.println("睡......");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 子类 Bird —— 继承 Animal,追加 fly 方法
|
|
|
+public class Bird extends Animal {
|
|
|
+ public void fly() {
|
|
|
+ System.out.println("飞.......");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 子类 Penguin —— 继承 Bird(多层继承)
|
|
|
+public class Penguin extends Bird {
|
|
|
+ // 继承了 Animal 的 eat()、sleep() 和 Bird 的 fly()
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 4. 继承的使用
|
|
|
+
|
|
|
+**文件**:`Test01.java`
|
|
|
+
|
|
|
+```java
|
|
|
+public class Test01 {
|
|
|
+ public static void main(String[] args) {
|
|
|
+ // 父类对象只能使用自己的方法
|
|
|
+ Animal animal = new Animal();
|
|
|
+ animal.eat();
|
|
|
+ animal.sleep();
|
|
|
+
|
|
|
+ // Bird 对象可以使用父类 Animal 的方法 + 自己的方法
|
|
|
+ Bird bird = new Bird();
|
|
|
+ bird.eat(); // 继承自 Animal
|
|
|
+ bird.sleep(); // 继承自 Animal
|
|
|
+ bird.fly(); // 自己的方法
|
|
|
+
|
|
|
+ // Penguin 对象可以使用所有继承来的方法
|
|
|
+ Penguin p = new Penguin();
|
|
|
+ p.eat(); // 继承自 Animal → Bird → Penguin
|
|
|
+ p.sleep(); // 继承自 Animal → Bird → Penguin
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 5. 继承的好处
|
|
|
+
|
|
|
+**文件**:`Demo01.java`
|
|
|
+
|
|
|
+| 好处 | 说明 |
|
|
|
+|------|------|
|
|
|
+| **代码复用性** | 多个类的相同成员可以放在同一个父类中,子类自动拥有 |
|
|
|
+| **代码可维护性** | 父类方法修改一处,所有子类都继承修改后的版本 |
|
|
|
+| **建立类与类的关系** | 产生父子类关系后,子类可使用父类中非私有化成员 |
|
|
|
+
|
|
|
+```java
|
|
|
+// 如果修改 Animal 的 eat() 方法,所有子类都会生效
|
|
|
+public class Animal {
|
|
|
+ public void eat() {
|
|
|
+ System.out.println("正在吃东西......"); // 改这里就行
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 6. 继承的弊端——耦合性
|
|
|
+
|
|
|
+**文件**:`Demo01.java`
|
|
|
+
|
|
|
+继承让类和类之间产生了关系,导致**耦合性增强**:
|
|
|
+- 父类发生变化时,子类也不得不跟着变化
|
|
|
+- 子类依赖父类的存在,如果父类不存在,子类就报错
|
|
|
+- 这削弱了子类的独立性
|
|
|
+
|
|
|
+> 耦合关系(Coupling):类与类之间的依赖程度。程序设计很多时候都在研究如何**解耦**。
|
|
|
+
|
|
|
+### 7. 继承的使用场景——is...a 关系
|
|
|
+
|
|
|
+**文件**:`Demo01.java`
|
|
|
+
|
|
|
+使用继承前要考虑类和类之间是否存在 **is...a** 关系(谁是谁的一种):
|
|
|
+
|
|
|
+| 正确(符合 is...a) | 错误(不符合 is...a) |
|
|
|
+|---------------------|----------------------|
|
|
|
+| 老师**是**人的一种 | 汽车**是**学生的一种 ✗ |
|
|
|
+| 学生**是**人的一种 | |
|
|
|
+| 人**是**动物的一种 | |
|
|
|
+| 动物**是**生物的一种 | |
|
|
|
+
|
|
|
+```java
|
|
|
+// 正确的继承设计
|
|
|
+class Person { }
|
|
|
+class Student extends Person { } // 学生是人的一种 ✓
|
|
|
+
|
|
|
+// 错误的继承设计
|
|
|
+class Car { }
|
|
|
+class Student extends Car { } // 学生不是汽车的一种 ✗
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、随堂练习——学生成绩管理系统(构造方法版)
|
|
|
+
|
|
|
+**包名**:`exercise.studentSystem`
|
|
|
+
|
|
|
+### 题目要求
|
|
|
+
|
|
|
+使用构造方法完成完整的学生成绩管理系统,包含三个类:
|
|
|
+
|
|
|
+### Student 类(实体类)
|
|
|
+
|
|
|
+**文件**:`Student.java`
|
|
|
+
|
|
|
+```java
|
|
|
+public class Student {
|
|
|
+ private int id; // 学号
|
|
|
+ private String name; // 姓名
|
|
|
+ private double javaScore; // Java 成绩
|
|
|
+ private double mysqlScore;// MySQL 成绩
|
|
|
+
|
|
|
+ // 全参构造方法
|
|
|
+ public Student(int id, String name, double javaScore, double mysqlScore) {
|
|
|
+ this.id = id;
|
|
|
+ this.name = name;
|
|
|
+ this.javaScore = javaScore;
|
|
|
+ this.mysqlScore = mysqlScore;
|
|
|
+ }
|
|
|
+
|
|
|
+ // getter/setter...
|
|
|
+
|
|
|
+ // 计算平均分的方法
|
|
|
+ public double getAverage() {
|
|
|
+ return (this.javaScore + this.mysqlScore) / 2;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### StudentSystem 类(业务类)
|
|
|
+
|
|
|
+**文件**:`StudentSystem.java`
|
|
|
+
|
|
|
+```java
|
|
|
+public class StudentSystem {
|
|
|
+ private Student[] students; // 学生数组
|
|
|
+ private int count; // 当前学生数量
|
|
|
+
|
|
|
+ // 构造方法:初始化指定容量的学生数组
|
|
|
+ public StudentSystem(int capacity) {
|
|
|
+ students = new Student[capacity];
|
|
|
+ count = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加学生到数组中
|
|
|
+ public void addStudent(Student s) {
|
|
|
+ if (count >= this.students.length) {
|
|
|
+ System.out.println("数组已满,添加失败");
|
|
|
+ } else {
|
|
|
+ students[count] = s;
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 输出所有学生信息(含平均分)
|
|
|
+ public void printAll() {
|
|
|
+ for (Student s : students) {
|
|
|
+ System.out.println("学号:" + s.getId() + ",姓名:" + s.getName()
|
|
|
+ + ",Java成绩:" + s.getJavaScore() + ",MySQL成绩:" + s.getMysqlScore()
|
|
|
+ + ",平均成绩:" + s.getAverage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按平均分降序排序(冒泡排序)
|
|
|
+ public void sortByAverage() {
|
|
|
+ for (int i = 0; i < students.length - 1; i++) {
|
|
|
+ for (int j = 0; j < students.length - 1 - i; j++) {
|
|
|
+ if (students[j].getAverage() < students[j + 1].getAverage()) {
|
|
|
+ Student temp = students[j];
|
|
|
+ students[j] = students[j + 1];
|
|
|
+ students[j + 1] = temp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 返回平均分最高的学生对象
|
|
|
+ public Student getTopStudent() {
|
|
|
+ Student s = students[0];
|
|
|
+ for (int i = 1; i < students.length; i++) {
|
|
|
+ if (s.getAverage() < students[i].getAverage()) {
|
|
|
+ s = students[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return s;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 涉及知识点
|
|
|
+
|
|
|
+| 知识点 | 说明 |
|
|
|
+|--------|------|
|
|
|
+| 全参构造方法 | 创建对象时直接初始化所有属性 |
|
|
|
+| 对象数组 | 存储多个学生对象 |
|
|
|
+| 增强 for 循环 | 遍历数组输出信息 |
|
|
|
+| 冒泡排序 | 按对象属性(平均分)排序 |
|
|
|
+| 方法调用链 | `students[j].getAverage()` 获取对象属性进行比较 |
|
|
|
+| 数组满判断 | `count >= students.length` 防止越界 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、课后作业
|
|
|
+
|
|
|
+### 作业 1:猜数游戏(面向对象版)⭐️⭐️⭐️⭐️
|
|
|
+
|
|
|
+**包名**:`homework.p08_guessgame`
|
|
|
+
|
|
|
+**文件**:`GuessGame.java`、`GuessGameTest.java`
|
|
|
+
|
|
|
+使用构造方法 + Random + 方法,将猜数字游戏改造为面向对象版本。
|
|
|
+
|
|
|
+**GuessGame 类**:
|
|
|
+```java
|
|
|
+public class GuessGame {
|
|
|
+ private int target; // 目标数字(随机生成)
|
|
|
+ private int maxRange; // 最大范围
|
|
|
+ private int attempts; // 已猜次数
|
|
|
+
|
|
|
+ // 构造方法:生成随机目标数字
|
|
|
+ public GuessGame(int maxRange) {
|
|
|
+ Random random = new Random();
|
|
|
+ this.maxRange = maxRange;
|
|
|
+ this.attempts = 0;
|
|
|
+ target = random.nextInt(this.maxRange) + 1; // 1~maxRange
|
|
|
+ }
|
|
|
+
|
|
|
+ // 猜数字方法
|
|
|
+ public String guess(int num) {
|
|
|
+ this.attempts++;
|
|
|
+ if (num > target) {
|
|
|
+ return "猜大了";
|
|
|
+ } else if (num < this.target) {
|
|
|
+ return "猜小了";
|
|
|
+ } else {
|
|
|
+ return "猜对了";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getAttempts() {
|
|
|
+ return this.attempts;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**GuessGameTest 测试类**:
|
|
|
+```java
|
|
|
+public class GuessGameTest {
|
|
|
+ public static void main(String[] args) {
|
|
|
+ GuessGame gg = new GuessGame(100);
|
|
|
+ Scanner sc = new Scanner(System.in);
|
|
|
+ while (true) {
|
|
|
+ System.out.print("请输入你猜的数字:");
|
|
|
+ int num = sc.nextInt();
|
|
|
+ String guess = gg.guess(num);
|
|
|
+ System.out.println(guess);
|
|
|
+ if (guess == "猜对了") { // 注意:字符串比较建议用 equals()
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ System.out.println("恭喜你!一共猜了 " + gg.getAttempts() + " 次");
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 作业 2:BookManager 图书管理系统 ⭐️⭐️⭐️⭐️
|
|
|
+
|
|
|
+**包名**:`homework.p09_bookmanager`
|
|
|
+
|
|
|
+**文件**:`Book.java`、`BookManager.java`、`BookManagerTest.java`
|
|
|
+
|
|
|
+综合练习:构造方法 + 封装 + 对象数组 + 排序 + 查找
|
|
|
+
|
|
|
+**Book 类**(实体类):
|
|
|
+```java
|
|
|
+public class Book {
|
|
|
+ private int id; // 编号
|
|
|
+ private String title; // 书名
|
|
|
+ private double price; // 价格
|
|
|
+
|
|
|
+ // 全参构造方法
|
|
|
+ public Book(int id, String title, double price) {
|
|
|
+ this.id = id;
|
|
|
+ this.title = title;
|
|
|
+ this.price = price;
|
|
|
+ }
|
|
|
+ // getter/setter...
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**BookManager 类**(业务类):
|
|
|
+```java
|
|
|
+public class BookManager {
|
|
|
+ // 初始化 5 本图书
|
|
|
+ public Book[] initBooks() {
|
|
|
+ Book b1 = new Book(1001, "Java从入门到精通", 79.0);
|
|
|
+ Book b2 = new Book(1002, "数据结构与算法", 65.0);
|
|
|
+ Book b3 = new Book(1003, "设计模式之禅", 58.0);
|
|
|
+ Book b4 = new Book(1004, "深入理解JVM", 89.0);
|
|
|
+ Book b5 = new Book(1005, "计算机网络", 45.0);
|
|
|
+ Book[] books = {b1, b2, b3, b4, b5}; // 静态初始化
|
|
|
+ return books;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 遍历所有图书
|
|
|
+ public void printBooks(Book[] books) {
|
|
|
+ for (Book b : books) {
|
|
|
+ System.out.println("编号:" + b.getId() + ",书名:" + b.getTitle()
|
|
|
+ + ",价格:" + b.getPrice());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按价格从高到低排序(冒泡排序)
|
|
|
+ public void sortByPrice(Book[] books) {
|
|
|
+ for (int i = 0; i < books.length - 1; i++) {
|
|
|
+ for (int j = 0; j < books.length - 1 - i; j++) {
|
|
|
+ if (books[j].getPrice() < books[j + 1].getPrice()) {
|
|
|
+ Book temp = books[j];
|
|
|
+ books[j] = books[j + 1];
|
|
|
+ books[j + 1] = temp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据书名查找图书
|
|
|
+ public Book searchByTitle(Book[] books, String title) {
|
|
|
+ for (Book b : books) {
|
|
|
+ if (b.getTitle() == title) { // 建议用 equals()
|
|
|
+ return b;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**BookManagerTest 测试类**:
|
|
|
+```java
|
|
|
+public class BookManagerTest {
|
|
|
+ public static void main(String[] args) {
|
|
|
+ BookManager bm = new BookManager();
|
|
|
+ Book[] books = bm.initBooks();
|
|
|
+
|
|
|
+ System.out.println("========== 原始顺序 ==========");
|
|
|
+ bm.printBooks(books);
|
|
|
+
|
|
|
+ bm.sortByPrice(books);
|
|
|
+ System.out.println("========== 按价格从高到低排序 ==========");
|
|
|
+ bm.printBooks(books);
|
|
|
+
|
|
|
+ System.out.println("========== 查找图书 ==========");
|
|
|
+ String bookName = "设计模式之禅";
|
|
|
+ Book book = bm.searchByTitle(books, bookName);
|
|
|
+ if (book == null) {
|
|
|
+ System.out.println("未找到该图书!");
|
|
|
+ } else {
|
|
|
+ System.out.println("找到了!编号:" + book.getId() + ",价格:" + book.getPrice());
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、今日知识点总结
|
|
|
+
|
|
|
+### 核心知识点
|
|
|
+
|
|
|
+| 知识点 | 重要程度 | 说明 |
|
|
|
+|--------|---------|------|
|
|
|
+| **继承的概念** | ⭐⭐⭐⭐⭐ | Java 三大特征之一,子类 extends 父类 |
|
|
|
+| **继承的格式** | ⭐⭐⭐⭐⭐ | `class 子类 extends 父类 {}` |
|
|
|
+| **继承的好处** | ⭐⭐⭐⭐ | 提高代码复用性和可维护性 |
|
|
|
+| **继承的弊端(耦合性)** | ⭐⭐⭐⭐ | 父类变化影响子类,降低独立性 |
|
|
|
+| **is...a 关系判断** | ⭐⭐⭐⭐ | 使用继承前必须判断是否符合 is...a |
|
|
|
+| **多层继承** | ⭐⭐⭐ | 一个类可继承自另一个已继承的子类 |
|
|
|
+| **构造方法 + 对象数组 + 冒泡排序综合应用** | ⭐⭐⭐⭐⭐ | 学生管理系统、图书管理系统 |
|
|
|
+
|
|
|
+### 注意事项
|
|
|
+
|
|
|
+1. **继承是单继承**:Java 中一个类只能有一个直接父类(单继承体系)
|
|
|
+2. **私有成员不可继承**:子类不能使用父类中 `private` 修饰的成员
|
|
|
+3. **构造方法不可继承**:父类的构造方法不会被子类继承,但子类可以通过 `super()` 调用
|
|
|
+4. **继承的耦合性**:合理设计继承层次,避免过深的继承链
|
|
|
+
|
|
|
+### 拓展阅读
|
|
|
+
|
|
|
+- Java 继承中 `super` 关键字的使用
|
|
|
+- 方法重写(Override)与方法重载(Overload)的区别
|
|
|
+- `final` 关键字对继承的限制(`final` 类不能被继承,`final` 方法不能被重写)
|
|
|
+- 继承与组合(Composition)的对比——优先使用组合而非继承
|