用final修饰类或方法是编译期强制禁止继承或重写的最可靠方式:final类不可被继承,final方法不可被重写,适用于工具类、不可变对象及关键逻辑,需谨慎评估扩展需求与兼容性。

直接用 final 修饰类或方法,是最明确、最可靠的禁止继承或重写的方式——它不是靠约定,而是编译期强制拦截。
用 final 修饰类:彻底关死继承入口
在 class 关键字前加 final,该类就再也不能被任何类继承。编译器一看到 class Sub extends FinalClass 就立刻报错:Cannot inherit from final 'FinalClass'。
- 典型场景包括工具类(如
Math、StringUtils)、不可变值对象(如String、LocalDate)、封装了安全逻辑且绝不允许语义变更的配置类 - final 类仍可继承其他类、实现接口,只是它自己不能成为父类
- 类一旦设为 final,里面所有实例方法自动“事实不可重写”(因为没子类),但显式加
final是更清晰的设计表达 - 避免矛盾用法:不要给抽象类加
final,也不要在已有private构造器的类上重复加final(冗余)
用 final 修饰方法:保留继承,锁住关键行为
在方法返回类型前加 final,表示这个方法可以被子类继承、调用,但绝不能被覆盖(@Override)。哪怕子类写了同签名方法,也会编译失败。
- 适合模板方法模式中的骨架逻辑(如
execute())、含校验/清理/日志等固定步骤的方法 - final 方法仍可被重载(overload),只要参数列表不同;禁止的只是重写(override)
- private 方法本身不可见、不可继承,加
final没意义,属于冗余写法 - 构造方法、接口中的实例方法都不能用
final修饰(语法错误)
设计时的关键判断点
加 final 不是技术炫技,而是契约声明:你已确认此处“绝不允许扩展”。加之前需确认:
- 这个类是否真没有合理子类化需求?比如值对象、工具类通常适合;而需要策略扩展的服务类就不适合
- 这个方法的行为是否必须稳定?比如涉及线程安全、幂等性、数据一致性校验的核心逻辑
- 已有代码中是否存在继承链?对已发布的类加
final可能导致依赖方编译失败 - 测试是否受影响?某些 mock 工具(如 CGLIB)无法代理 final 类或方法,需改用接口或 Mockito 的 mockito-inline
替代与补充思路
如果想保留一定扩展性,又不想完全开放继承,可考虑更精细的控制方式:
- Java 17+ 的
sealed类:明确列出允许继承的子类,比final更灵活 - 包级私有类(不写访问修饰符):仅限同包继承,天然限制作用域
- 模板方法 + private/final 核心步骤:把可变部分定义为
protected abstract钩子,固定部分用final封装


















