必须用final锁死的关键算法步骤包括:身份校验入口(如checkPermission)、模板方法主干(如executeWorkflow)、状态跃迁控制(如transitionToFinalState)、数据签名验证逻辑(如verifySignature);final须置于访问修饰符后、返回类型前,private或static方法加final属冗余或错误;final是模板方法模式关键支撑,保障流程骨架不可变、钩子可扩展;但其不解决mock难题、违背开闭原则风险及运行时防护缺失。

直接在关键步骤方法前加 final,编译器会在子类尝试重写时立刻报错,从源头切断干预可能。
哪些算法步骤必须用 final 锁死
不是所有方法都需要加 final,重点保护那些一旦被改动,就会让整个流程失去可信度的环节:
- 身份校验入口,比如
checkPermission()—— 子类绕过会导致越权 - 模板方法中的主干调用,如
executeWorkflow()—— 它串联多个钩子方法,自身不能被替换 - 状态跃迁控制,例如
transitionToFinalState()—— 跳过中间校验直接设终态会破坏业务约束 - 数据签名验证逻辑,像
verifySignature(byte[] data)—— 修改可能使篡改行为无法被发现
声明位置和常见语法陷阱
final 必须放在访问修饰符之后、返回类型之前,顺序错误虽能编译但不规范:
- ✅ 正确:
public final void validateInput() - ⚠️ 不推荐:
final public void validateInput()(语法允许,但违背通用约定) - ❌ 无效:
private final void init()—— private 方法天然不可重写,加 final 是冗余 - ❌ 错误:
static final void helper()—— static 方法本就不能被重写,“重写”概念不成立,只存在隐藏
和模板方法模式配合使用
final 方法是模板方法模式落地的关键支撑。父类把流程骨架定死,只开放抽象钩子供子类实现:
- 主流程方法用
public final void templateMethod()封装整体顺序 - 具体步骤声明为
protected abstract void doStepX(),由子类自由实现 - 子类能参与定制,但无法打乱或跳过核心环节,逻辑一致性由编译器强制保障
注意它不解决所有问题
final 是强契约,但不是万能补丁:
- 加了 final 的方法在单元测试中难以 mock,除非启用 inline mock 模式并配置 JVM 参数
- 未来真需调整逻辑时,子类只能复制整段代码再改,违背开闭原则
- 如果频繁想绕过 final 限制,说明设计上更该考虑解耦 —— 把算法抽成独立类,用组合代替继承
- 运行时仍需配合断言或 SecurityManager 做二次防护,final 只管编译期行为锁定

















