抽象类通过abstract方法设编译期硬性门槛,子类必须实现否则编译失败;配合final模板方法固化流程,仅开放protected abstract插槽供子类定制核心逻辑,并利用构造器校验参数、初始化final字段。

抽象类通过抽象方法在编译期设下硬性门槛,让子类无法绕过关键逻辑的实现——没写完就编译失败,不是警告,是直接拦停。
抽象方法就是一道编译期“铁闸”
在抽象类里声明一个没方法体、带 abstract 修饰的方法,比如:
- protected abstract void validate();
- 它只定义“要做什么”,不规定“怎么做”
- 子类若是具体类(非 abstract),就必须用 @Override 实现它,否则编译报错:class Xxx must either be declared abstract or implement abstract method...
- 不能是 private、static 或 final——这些修饰符和“留给子类覆盖”的本意冲突
- 访问权限推荐用 public 或 protected,确保子类能看见、能重写
靠模板方法把流程“焊死”,只留插槽给子类填
光有抽象方法只能卡住“有没有写”,真正管住“怎么用”,得靠 final 方法封装主干流程:
- 写一个 public final void execute(),内部按顺序调用 prepare() → doCore() → cleanup()
- 其中 doCore() 设为 protected abstract,强制子类提供自己的核心逻辑
- prepare() 和 cleanup() 可以是父类的具体方法,所有子类复用,不用重复写事务、日志、校验
- 子类只能改 doCore(),不能动执行顺序,流程一致性就有了保障
用 protected abstract 精准暴露业务差异点
实际开发中,需要差异化的地方往往很聚焦。把这些关键决策点单独拎出来,声明为 protected abstract:
- protected abstract BigDecimal calculateFee(Order order);
- protected abstract String generateTraceId();
- 既限制了访问范围(子类可用,外部不可见),又明确了责任归属
- 子类不必操心通用环节,只专注回答“我怎么算费”“我怎么生成追踪号”这类问题
构造器 + final 字段守住初始化底线
抽象类虽不能 new,但它的构造器会在子类实例化时自动执行。这里可以做两件事:
- 校验入参:比如检查配置项不能为空、金额不能为负,不合规就抛 IllegalArgumentException
- 初始化 protected final 字段:如 protected final String apiEndpoint;,确保一创建就带上不可变上下文
- 避免在构造器里调用抽象方法——此时子类字段还没初始化,容易空指针
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











