抽象类通过编译强制、流程固化与职责隔离划定不可绕过的责任边界:用public abstract方法卡住核心业务入口,final模板方法锁死执行骨架,钩子方法支持可选扩展,严格剥离具体实现以守住抽象职责。

抽象类限制子类行为,关键不是“限制自由”,而是“划定不可绕过的责任边界”——通过编译期强制 + 流程固化 + 职责隔离,让核心逻辑既不被跳过,也不被污染。
用抽象方法卡住必须实现的业务入口
把真正决定业务成败的环节声明为 public abstract 方法。编译器会确保:只要子类不是 abstract 的,就必须提供实现,否则直接编译失败。
- 例如
protected abstract BigDecimal calculateFee(Order order);—— 费率计算逻辑不能由父类代劳,也不能被子类忽略 - 不能写
private abstract或static abstract,语法不合法,IDE 会标红 - 子类实现时,返回类型可协变(如父类返回
Number,子类返回BigDecimal),但参数类型必须完全一致
用 final 模板方法锁死执行流程骨架
把校验、日志、事务、结果包装等通用控制逻辑,封装进 final 方法中,再在其中调用抽象方法。子类无法重写主干,只能填空。
- 例如
public final void execute() { preCheck(); doBusiness(); postNotify(); } - 其中
doBusiness()是抽象方法,子类必须实现;preCheck()和postNotify()是父类提供的具体逻辑,统一保障安全水位 - 避免在抽象类构造器里调用任何抽象方法——此时子类字段尚未初始化,极易触发
NullPointerException
用钩子方法支持可选扩展,不破坏契约
对非核心但可能需要定制的行为,提供空的 protected 方法作为扩展点,子类按需重写,不重写也不影响主流程。
- 例如
protected void onRetryExhausted(Order order) { }—— 重试失败后是否告警、落库、人工介入,由子类决定 - 命名建议用
onXXX、afterXXX或beforeXXX,语义清晰,不混淆强制与可选 - 这类方法不要加
abstract,否则变成强制项,违背设计意图
剥离具体业务,守住抽象类的职责边界
抽象类不是业务容器。一旦出现数据库操作、HTTP 调用、硬编码状态判断(如 if (status == "SHIPPED")),就说明它已越界。
- 把数据访问移出,交给
Repository接口,由子类注入或委托 - 把通知逻辑抽成
Notifier接口,抽象类只依赖接口,不关心短信还是邮件 - 禁止在抽象类中注入多个服务(如
OrderService+SmsSender+RedisTemplate),这是上帝类信号
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











