抽象类中模板方法必须声明为public final void,以锁死算法骨架;final防止子类重写,确保校验、处理、保存等流程顺序不可篡改,避免安全漏洞、数据不一致及维护混乱。

抽象类中把模板方法声明为 public final void,是防止业务子类篡改流程最直接、最可靠的手段。Java 编译器会在子类尝试重写该方法时立即报错,从源头切断流程被覆盖或打乱的可能。
为什么 final 能真正锁死流程
模板方法本质是算法骨架的“总指挥”,它按固定顺序调用一系列步骤方法。一旦被子类重写,整个执行顺序、条件判断、异常处理逻辑都可能被替换或跳过——这等于把父类的设计意图完全架空。
- final 方法无法被继承重写,子类连签名都不能改
- 即使子类定义同名方法,也只是隐藏(hide),不会参与多态调用
- 客户端始终通过父类引用调用,确保走的是原始骨架
关键位置必须加 final 的方法
不是所有方法都需要 final,但以下几类必须加,否则流程一致性就失去保障:
-
主模板方法本身:如
public final void process(),这是整个模式的入口和中枢 -
身份/权限校验入口:如
final void checkPermission(),绕过会导致安全漏洞 -
状态跃迁控制方法:如
final void transitionToConfirmed(),跳过中间校验会破坏业务约束 -
数据完整性验证逻辑:如
final boolean verifySignature(byte[] data),修改可能使篡改不可见
配合使用的访问与修饰规范
final 的效果依赖正确的位置和搭配:
- 写法必须是
public final void methodName(),final紧跟在访问修饰符后、返回类型前 - 避免对
private或static方法加 final —— 前者天然不可重写,后者不参与重写机制,加了也无效 - 模板方法通常设为
public(供外部调用)或protected(仅限子类链内使用),但不能是private - 被模板方法调用的步骤方法,应保持
protected abstract或protected(带默认实现),不加 final,以便子类自由实现
不靠 final 就容易出问题的典型场景
很多团队初期没加 final,结果出现这些实际问题:
- 子类重写了模板方法,把“校验→处理→保存”改成“处理→校验→保存”,导致非法数据进入处理环节
- 某个子类悄悄删掉日志记录步骤,线上出问题时无法追溯执行路径
- 不同子类对同一模板方法给出不同实现,同一接口调用却产生不一致行为,违反里氏替换原则
- 新同学接手时误以为“父类只是个参考”,直接复制整段流程再魔改,造成逻辑重复和维护断层
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











