Java 抽象类与抽象方法:规范契约、强制实现与模板模式
抽象是隐藏实现细节、仅暴露功能接口的过程。Java 通过 abstract 关键字实现抽象类与抽象方法,定义“必须做什么”,留给子类决定“怎么做”。
抽象类
含 abstract 修饰的类,不能实例化。可包含:
- 抽象方法(无方法体,以分号结尾)
- 具体方法(有实现)
- 字段、构造器、静态成员、内部类等
关键规则
- 含抽象方法 ⇒ 类必须声明 abstract
- abstract 类可无抽象方法(仅防止实例化)
- 子类继承抽象类必须实现所有抽象方法,否则子类也必须声明 abstract
- 抽象类构造器供子类
super()调用,不可直接 new
抽象类示例:Employee
public abstract class Employee {
private String name, address; int number;
public Employee(String name, String address, int number) {
this.name = name; this.address = address; this.number = number;
}
// 抽象方法:强制子类实现薪资计算逻辑
public abstract double computePay();
// 具体方法:通用邮寄逻辑
public void mailCheck() {
System.out.println("邮寄支票给 " + name + " " + address);
}
// ... getter/setter
}
继承抽象类
public class Salary extends Employee {
private double salary;
public Salary(String name, String address, int number, double salary) {
super(name, address, number);
this.salary = salary;
}
@Override
public double computePay() { // 必须实现
return salary / 52; // 周薪
}
@Override
public void mailCheck() { // 可选重写
System.out.println("Salary 邮寄: " + getName() + " 薪资 " + salary);
}
}
多态使用抽象类引用
Employee e = new Salary("John", "Boston", 1, 2400);
e.mailCheck(); // 调用 Salary 重写版本
System.out.println(e.computePay()); // 多态调用子类实现
抽象方法
public abstract double computePay(); // 无大括号,以分号结束
声明在抽象类中,强制子类提供实现。接口中方法默认即为抽象(Java 8 前)。
抽象类 vs 接口(Java 8+ 视角)
| 维度 | 抽象类 | 接口 |
|---|---|---|
| 关键字 | abstract class | interface |
| 继承/实现 | extends(单继承) | implements(多实现) |
| 字段 | 任意实例/静态字段 | 仅 static final 常量 |
| 构造器 | 有 | 无 |
| 方法 | 抽象+具体+静态+私有 | 抽象+default+static+私有 |
| 访问修饰 | 任意 | 隐式 public |
| 适用场景 | 强关联、共享状态/代码 | 能力定义、松耦合、多实现 |
模板方法模式:抽象类经典应用
在抽象类定义算法骨架,将变化步骤延迟到子类实现。
abstract class DataProcessor {
// 模板方法:final 防止重写破坏流程
public final void process() {
readData();
transformData(); // 抽象步骤
writeData();
}
void readData() { System.out.println("读取数据"); }
abstract void transformData(); // 子类实现
void writeData() { System.out.println("写入数据"); }
}
class CsvProcessor extends DataProcessor {
@Override void transformData() { System.out.println("CSV 转换"); }
}
class JsonProcessor extends DataProcessor {
@Override void transformData() { System.out.println("JSON 转换"); }
}
最佳实践
- 抽象类建模“is-a”强关联,接口建模“has-a”能力
- 优先用接口,需共享代码/状态时再引入抽象类
- 抽象方法命名体现意图(如
computePay而非calc) - 模板方法标记
final保护算法结构 - 避免过深抽象层次,YAGNI 原则
java
- 深入理解 Java final 关键字:变量、方法与类的不可变性
- Java instanceof 运算符完全指南:用法、继承与接口检查
- 精通 Java 继承:核心概念、类型与实战示例
- Java 抽象类与抽象方法完全指南
- 深入理解 Java 静态嵌套类:用法、差异与实战示例
- 精通 Java 匿名内部类:定义、语法与实战示例
- Java 单例模式详解:安全实现与使用指南
- 精通 Java 反射:运行时检查类、方法与字段
- 掌握 Java ObjectOutputStream:序列化、核心方法与实战示例
- 掌握 Java 泛型:构建可复用、类型安全的代码
- 掌握 Java 文件操作:java.io 包下的创建、读取、写入与删除
- Java 接口 vs 抽象类:如何选择合适的抽象方式