# JavaSE 基础 — Day09 笔记 > **日期**:2026-07-23 > **项目**:`c260723` > **作者**:WanJL --- ## 一、抽象类(Abstract Class) ### 1. 抽象类的引出 **文件**:`Demo01.java` 在父子类继承时,提取子类的共性功能时,有些方法在父类中并没有具体的实现。 例如员工体系: ``` 员工类 |- 开发工程师 |- Java开发工程师 |- 前端开发工程师 |- 测试工程师 |- 后端测试工程师 |- IOS测试工程师 ``` 每一个子类的工作内容都是不一样的,所以都需要重写父类的 `work()` 方法,导致父类的 `work()` 方法代码没有实际作用。 ```java public class 员工 { public void work() { // 每一个子类的工作内容都不一样,此方法体没有意义 } } ``` 在 Java 中,一个没有方法体的方法,应该定义为 **抽象方法**;如果类中包含抽象方法,那么这个类必须是 **抽象类**。 ### 2. 抽象类的定义 **文件**:`Demo01.java` 使用 `abstract` 关键字来定义抽象类和抽象方法。 **定义抽象类**: ```java public abstract class 类名 { // 成员 } ``` **定义抽象方法**: ```java public abstract 返回值类型 方法名(参数列表); ``` > **注意**:抽象方法没有方法体(没有 `{}`,直接以分号结尾)。 ### 3. 抽象类的特点 **文件**:`Demo01.java` | 特性 | 说明 | |------|------| | **关键字** | 抽象类和抽象方法必须使用 `abstract` 关键字修饰 | | **抽象方法所在类** | 有抽象方法的类必须是抽象类 | | **抽象类中的抽象方法** | 抽象类中不一定要有抽象方法,但抽象方法必须在抽象类中 | | **实例化** | **抽象类不能实例化(不能创建对象)** | | **构造方法** | 抽象类可以有构造方法(供子类通过 `super()` 调用) | | **子类选择** | ① 重写父类所有的抽象方法;② 子类也是抽象类,直接继承父类的抽象方法 | | **继承关系** | 抽象父类和具体子类之间是继承关系,子类仍然属于父类类型 | --- ## 二、抽象类代码示例 ### 示例 1:动物体系(Animal → Cat / Dog) #### 抽象父类 Animal **文件**:`Animal.java` ```java package course; public abstract class Animal { public Animal() { System.out.println("调用动物的构造方法...."); } public abstract void eat(); public abstract void sleep(); public abstract void move(); public abstract void play(); } ``` - 定义了 4 个抽象方法:`eat()`、`sleep()`、`move()`、`play()` - 包含一个构造方法,虽然抽象类不能直接创建对象,但构造方法可以通过子类 `super()` 调用 #### 子类 Cat **文件**:`Cat.java` ```java package course; public class Cat extends Animal { @Override public void eat() { System.out.println("猫吃鱼"); } @Override public void sleep() { // 空实现 } @Override public void move() { // 空实现 } @Override public void play() { // 空实现 } } ``` - 使用 `extends` 继承抽象类 `Animal` - 使用 `@Override` 注解重写父类的所有抽象方法(必须全部重写,否则子类也要声明为抽象类) #### 子类 Dog **文件**:`Dog.java` ```java package course; public class Dog extends Animal { public void eat() { System.out.println("狗吃肉"); } @Override public void sleep() { } @Override public void move() { } @Override public void play() { } } ``` - 同样继承 `Animal`,重写所有抽象方法 - `eat()` 方法没有写 `@Override` 注解,但仍然是对父类抽象方法的重写(注解只是编译检查,不写也能重写) #### 测试类 Test01 **文件**:`Test01.java` ```java package course; public class Test01 { public static void main(String[] args) { Dog dog = new Dog(); dog.eat(); // 输出:狗吃肉 } } ``` - 创建 `Dog` 对象,调用重写后的 `eat()` 方法 - 验证了抽象类的子类可以正常创建对象和使用成员方法 --- ### 示例 2:员工体系(Emp → javaEmp) #### 抽象父类 Emp **文件**:`Emp.java` ```java package course; // 有抽象方法的类必须是抽象类 public abstract class Emp { /** * 抽象方法——没有方法体 */ public abstract void work(); } ``` - 只定义了一个抽象方法 `work()` - 类必须使用 `abstract` 修饰 #### 子类 javaEmp **文件**:`javaEmp.java` ```java package course; public class javaEmp extends Emp { @Override public void work() { System.out.println("Java开发工程师在开发Java项目"); } } ``` - 重写父类的 `work()` 抽象方法,给出具体的实现 - 不同子类可以提供不同的实现(例如还可以有 `前端开发工程师`、`后端测试工程师` 等) --- ### 示例 3:服务层体系(BaseService → UserService) #### 抽象父类 BaseService **文件**:`BaseService.java` ```java package course; public abstract class BaseService { public abstract void add(); public abstract void remove(); public abstract void update(); public abstract void query(); } ``` - 定义了标准的 CRUD(增删改查)四个抽象方法 - 在实际项目中常用来定义业务层接口规范 #### 子类 UserService **文件**:`UserService.java` ```java package course; public class UserService extends BaseService { @Override public void add() { } @Override public void remove() { } @Override public void update() { } @Override public void query() { } } ``` - 重写父类的所有抽象方法 - 方法体暂时为空,后续可添加具体的业务逻辑 --- ## 三、随堂练习要点 **练习目标**:理解抽象类的定义和使用 1. **定义抽象父类**:使用 `public abstract class` 声明,定义抽象方法时不要写方法体 2. **实现具体子类**:使用 `extends` 继承抽象类,使用 `@Override` 重写所有抽象方法 3. **测试类验证**:创建子类对象,调用重写后的方法验证正确性 --- ## 四、面试常见问题 **Q1:抽象类能不能被实例化?** > 不能。抽象类不能直接 `new` 创建对象。 **Q2:抽象类中一定要有抽象方法吗?** > 不一定。抽象类中可以没有抽象方法,但有抽象方法的类必须是抽象类。 **Q3:抽象类的子类必须重写所有抽象方法吗?** > 不一定。子类有两个选择:① 重写父类所有抽象方法变为具体子类;② 子类也声明为抽象类,继承父类的抽象方法。 **Q4:抽象类可以有构造方法吗?** > 可以。虽然抽象类不能直接创建对象,但其构造方法可以在子类实例化时通过 `super()` 调用,用于初始化父类成员。 **Q5:`abstract` 和 `final` 能否同时修饰一个类或方法?** > 不能。`abstract` 表示需要被继承/重写,`final` 表示不能被继承/重写,二者语义冲突。 --- ## 五、拓展阅读 - [Java 抽象类(Oracle 官方文档)](https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html) - 抽象类 vs 接口(Interface)的区别(将在后续课程中讲解) - 模板方法设计模式(Template Method Pattern)—— 抽象类的经典应用场景