|
|
@@ -56,7 +56,7 @@ animal.eat(); // ✅ 编译看父类有 eat(),运行执行 Dog 的 eat()
|
|
|
animal.sleep(); // ✅ 编译看父类有 sleep()(抽象),运行执行 Dog 的 sleep()
|
|
|
// animal.wangWang(); // ❌ 编译报错,父类没有 wangWang()
|
|
|
```
|
|
|
-> 📄 来源:`Test01.java`、`Dog.java`
|
|
|
+> 📄 来源:`Test01.java`、`Dog.java`(`course.polymorphism` 包)
|
|
|
|
|
|
---
|
|
|
|
|
|
@@ -88,7 +88,7 @@ public class Mouse implements Usb {
|
|
|
public void stopUsb() { System.out.println("USB鼠标关闭"); }
|
|
|
}
|
|
|
```
|
|
|
-> 📄 来源:`Usb.java`、`NoteBook.java`、`Mouse.java`
|
|
|
+> 📄 来源:`Usb.java`、`NoteBook.java`、`Mouse.java`(`course.polymorphism` 包)
|
|
|
|
|
|
```java
|
|
|
// 测试多态
|
|
|
@@ -150,7 +150,7 @@ p.sleep(); // ✅ 父类中有 sleep()
|
|
|
Student s = (Student) p; // 向下转型
|
|
|
s.study(); // ✅ 转型后可以调用子类特有方法
|
|
|
```
|
|
|
-> 📄 来源:`Demo02.java`
|
|
|
+> 📄 来源:`Demo02.java`(`course.polymorphism` 包)
|
|
|
|
|
|
#### 1.5.3 instanceof 运算符——类型判断
|
|
|
|
|
|
@@ -175,7 +175,7 @@ public void 点外卖(外卖类 wm) {
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
-> 📄 来源:`Demo02.java`
|
|
|
+> 📄 来源:`Demo02.java`(`course.polymorphism` 包)
|
|
|
|
|
|
---
|
|
|
|
|
|
@@ -208,7 +208,7 @@ public class Test03 {
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
-> 📄 来源:`Test03.java`
|
|
|
+> 📄 来源:`Test03.java`(`course.polymorphism` 包)
|
|
|
|
|
|
**执行流程分析**(以传入 `new Student()` 为例):
|
|
|
```
|
|
|
@@ -232,7 +232,7 @@ public abstract class Animal {
|
|
|
public abstract void sleep(); // 抽象方法
|
|
|
}
|
|
|
```
|
|
|
-> 📄 来源:`Animal.java`
|
|
|
+> 📄 来源:`Animal.java`(`course.polymorphism` 包)
|
|
|
|
|
|
### 2.2 子类继承抽象类
|
|
|
|
|
|
@@ -251,7 +251,7 @@ public class Dog extends Animal {
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
-> 📄 来源:`Dog.java`
|
|
|
+> 📄 来源:`Dog.java`(`course.polymorphism` 包)
|
|
|
|
|
|
- 子类必须重写父类的所有抽象方法(除非子类也是抽象类)
|
|
|
- 子类可以重写父类的普通方法(`eat()`)
|
|
|
@@ -284,7 +284,7 @@ public class Teacher extends Person {
|
|
|
public void play() { System.out.println("教师玩....爽...."); } // 特有方法
|
|
|
}
|
|
|
```
|
|
|
-> 📄 来源:`Person.java`、`Student.java`、`Teacher.java`
|
|
|
+> 📄 来源:`Person.java`、`Student.java`、`Teacher.java`(`course.polymorphism` 包)
|
|
|
|
|
|
---
|
|
|
|
|
|
@@ -354,34 +354,174 @@ public class Test02 {
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
-> 📄 来源:`Test02.java`
|
|
|
+> 📄 来源:`Test02.java(course.polymorphism 包)`
|
|
|
|
|
|
> **关键点**:`NoteBook.useUsb(Usb usb)` 的参数类型是 **接口**,任何实现 `Usb` 接口的类都可以传入,无需修改笔记本的代码即可接入新设备——这就是 **多态提高扩展性** 的典型应用。
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 四、随堂练习要点
|
|
|
+## 四、内部类(Inner Class)
|
|
|
+
|
|
|
+### 4.1 什么是内部类
|
|
|
+
|
|
|
+**概念**:在一个类中定义另一个类。例如,在 `A` 类的内部定义了 `B` 类,`B` 就是内部类。
|
|
|
+
|
|
|
+**使用场景**:当一个类的属性不足以描述内部细节时使用。
|
|
|
+
|
|
|
+```java
|
|
|
+class 人类 { // 外部类
|
|
|
+ 心脏; // 仅一个属性无法表达心脏的复杂行为
|
|
|
+}
|
|
|
+
|
|
|
+class 汽车 { // 外部类
|
|
|
+ 发动机; // 发动机应有自己的属性和方法
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+> 心脏和发动机都依赖于「人类」和「汽车类」而存在,且它们本身也有自己的属性和方法,所以应该设计为 **内部类**。
|
|
|
+
|
|
|
+**定义格式**:
|
|
|
+```java
|
|
|
+class 外部类名 {
|
|
|
+ 修饰符 class 内部类名 {
|
|
|
+ // 内部类的成员
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 4.2 内部类的特点
|
|
|
+
|
|
|
+| 特点 | 说明 |
|
|
|
+|------|------|
|
|
|
+| **① 内部类可直接访问外部类所有成员** | 包括 private 修饰的成员 |
|
|
|
+| **② 外部类访问内部类成员需创建对象** | 外部类方法中 `new` 内部类对象后再调用 |
|
|
|
+
|
|
|
+```java
|
|
|
+public class Person {
|
|
|
+ private String name;
|
|
|
+
|
|
|
+ // 内部类
|
|
|
+ public class Heart {
|
|
|
+ public void jump() {
|
|
|
+ // 内部类直接访问外部类的私有成员
|
|
|
+ System.out.println(name + "的心脏跳动....");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 外部类方法——必须创建内部类对象才能访问
|
|
|
+ public void method() {
|
|
|
+ Heart h = new Heart();
|
|
|
+ h.jump();
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Demo01.java`(`course.internalClass` 包)
|
|
|
+
|
|
|
+### 4.3 成员内部类
|
|
|
+
|
|
|
+**成员内部类**:存在于外部类内部,属于外部类的成员,与成员变量、成员方法、代码块在同一层次。
|
|
|
+
|
|
|
+#### 创建格式
|
|
|
+
|
|
|
+```java
|
|
|
+外部类名.内部类名 对象名 = new 外部类().new 内部类();
|
|
|
+// 示例:
|
|
|
+Person.Heart h = new Person().new Heart();
|
|
|
+```
|
|
|
+
|
|
|
+#### 访问权限修饰符
|
|
|
+
|
|
|
+成员内部类可以使用访问权限修饰符(`private`、`public` 等)进行修饰。
|
|
|
+
|
|
|
+```java
|
|
|
+public class Person {
|
|
|
+ // 私有化内部类——外界无法直接访问
|
|
|
+ private class Heart {
|
|
|
+ // ...
|
|
|
+ }
|
|
|
+
|
|
|
+ // 对外提供公共方法获取内部类对象
|
|
|
+ public Heart getHeart() {
|
|
|
+ return new Heart();
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 为什么推荐私有化内部类?
|
|
|
+
|
|
|
+```java
|
|
|
+// ❌ 不合理的做法——Heart 和 Person 无关联
|
|
|
+public class Person {
|
|
|
+ Heart heart;
|
|
|
+}
|
|
|
+
|
|
|
+public class Test01 {
|
|
|
+ public static void main(String[] args) {
|
|
|
+ // 可以直接跳过 Person,单独创建 Heart 对象
|
|
|
+ Heart h = new Heart(); // 不符合现实逻辑
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// ✅ 合理的做法——Heart 作为 Person 的私有内部类
|
|
|
+public class Person {
|
|
|
+ private class Heart { // 私有内部类
|
|
|
+ public void jump() {
|
|
|
+ System.out.println("心脏跳动...");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public Heart getHeart() { // 对外提供方法
|
|
|
+ return new Heart();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+public class Test01 {
|
|
|
+ public static void main(String[] args) {
|
|
|
+ Person person = new Person();
|
|
|
+ // 必须通过 Person 对象才能获取 Heart
|
|
|
+ // person.getHeart(); // 这才是合理的调用链
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+> 📄 来源:`Demo01.java`、`Test01.java`(`course.internalClass` 包)
|
|
|
+
|
|
|
+> **设计原则**:内部类的设计目的就是 **不想让外界直接访问**,仅限外部类自己使用。所以内部类应该私有化,并通过外部类的公共方法对外开放。
|
|
|
+
|
|
|
+### 4.4 内部类与多态的对比
|
|
|
+
|
|
|
+| 对比维度 | 多态 | 内部类 |
|
|
|
+|---------|------|--------|
|
|
|
+| 解决什么问题 | 同一行为在不同子类中有不同实现 | 类的内部细节需要独立描述 |
|
|
|
+| 关系 | 父类/接口 ← 子类/实现类 | 外部类 → 内部类(强依赖) |
|
|
|
+| 访问特点 | 编译看左边,运行看右边 | 内部类可直接访问外部类私有成员 |
|
|
|
+
|
|
|
+## 五、随堂练习要点
|
|
|
|
|
|
| 练习方向 | 涉及知识点 | 对应文件 |
|
|
|
|---------|-----------|---------|
|
|
|
-| 多态入门 | 多态前提、父类引用指向子类对象、成员访问特点 | `Test01.java`、`Dog.java` |
|
|
|
-| 多态中的转型 | 向上转型、向下转型、instanceof 运算符 | `Demo02.java`、`Test03.java` |
|
|
|
+| 多态入门 | 多态前提、父类引用指向子类对象、成员访问特点 | `Test01.java(course.polymorphism 包)`、`Dog.java(course.polymorphism 包)` |
|
|
|
+| 多态中的转型 | 向上转型、向下转型、instanceof 运算符 | `Demo02.java(course.polymorphism 包)`、`Test03.java(course.polymorphism 包)` |
|
|
|
| 抽象类多态综合 | 抽象父类 Person、多态参数、向下转型调特有方法 | `Test03.java`、`Person.java` |
|
|
|
-| 接口多态 | Usb 接口、笔记本接入多设备 | `Test02.java`、`NoteBook.java` |
|
|
|
+| 接口多态 | Usb 接口、笔记本接入多设备 | `Test02.java(course.polymorphism 包)`、`NoteBook.java(course.polymorphism 包)` |
|
|
|
+| 内部类入门 | 内部类概念、成员内部类、私有内部类设计 | 包 `course.internalClass` |
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 五、拓展阅读 & 常见面试题
|
|
|
+## 六、拓展阅读 & 常见面试题
|
|
|
|
|
|
1. **多态的实现原理**——Java 中多态是通过**动态绑定(后期绑定)**实现的,JVM 在运行时根据对象的实际类型调用对应的方法。
|
|
|
2. **多态与继承的关系**——多态是基于继承或接口实现的。
|
|
|
3. **多态的优势**——提高代码的可扩展性和可维护性,符合**开闭原则**(对扩展开放,对修改关闭)。
|
|
|
4. **向下转型的风险**——向下转型必须配合 `instanceof` 判断,否则可能抛出 `ClassCastException`(类型转换异常)。
|
|
|
5. **instanceof 的用法**——常用于向下转型前的安全判断,避免强制类型转换异常。
|
|
|
+6. **内部类的使用场景**——当一个类的内部细节(如心脏之于人、发动机之于汽车)需要独立描述时,应设计为内部类。
|
|
|
+7. **内部类的访问规则**——内部类可直接访问外部类的所有成员(含 private);外部类必须创建内部类对象才能访问其成员。
|
|
|
+8. **私有内部类的设计原则**——内部类应私有化,并通过外部类的公共方法对外暴露,确保外部类对内部类的完全控制。
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 六、今日知识图谱
|
|
|
+## 七、今日知识图谱
|
|
|
|
|
|
```
|
|
|
面向对象三大特征
|
|
|
@@ -401,4 +541,16 @@ public class Test02 {
|
|
|
│ └── 格式:对象名 instanceof 类型(返回 boolean)
|
|
|
└── 多态的好处:提高扩展性(开闭原则)
|
|
|
└── 案例:NoteBook.useUsb(Usb usb)
|
|
|
+
|
|
|
+内部类 ⭐(今日新增)
|
|
|
+├── 概念:类中定义类(心脏之于人、发动机之于汽车)
|
|
|
+├── 特点
|
|
|
+│ ├── 内部类可直接访问外部类所有成员(含 private)
|
|
|
+│ └── 外部类需创建内部类对象才能访问其成员
|
|
|
+├── 成员内部类
|
|
|
+│ ├── 创建格式:外部类名.内部类名 对象名 = new 外部类().new 内部类();
|
|
|
+│ └── 可用访问权限修饰符修饰(private 等)
|
|
|
+└── 私有内部类设计原则
|
|
|
+ ├── 内部类私有化,不被外界直接访问
|
|
|
+ └── 外部类提供公共方法对外暴露内部类功能
|
|
|
```
|