final修饰类最直接的后果是彻底关闭继承通道,任何类都无法通过extends继承它,编译器会在编译期强制拦截并报错,不生成字节码;该类仍可实例化、实现接口、被组合使用,其非private方法自动具备final语义。

Java 中用 final 修饰一个类,最直接的后果就是:它彻底关闭了继承通道——任何类都不能通过 extends 继承它,编译器会在写子类时立刻报错,不给运行机会。
编译期强制拦截,不是运行时限制
这不是异常或警告,而是编译失败。只要代码里出现 class Sub extends FinalClass,javac 就会拒绝生成字节码,报类似这样的错误:
error: cannot inherit from final class FinalClass-
Cannot inherit from final 'xxx'(IDE 常见提示)
这意味着继承关系在代码写出来那一刻就被拦下,JVM 根本不会加载这种非法结构。
final 类仍可被正常使用
不能继承 ≠ 不能使用。final 类完全支持:
- 被实例化(
new FinalClass()) - 实现接口(
final class A implements Runnable) - 被其他类组合(has-a 关系,比如字段类型是 final 类)
- 序列化与反序列化(只要满足 Serializable 规则)
只是它无法作为父类参与 extends 链,也不允许子类覆盖它的任何方法——因为根本没子类。
内部方法自动具备 final 语义
final 类中的所有实例方法(非 private)天然不可被重写,哪怕你没显式加 final 修饰符。这是因为没有子类能继承它,重写也就无从谈起。
- private 方法本来就不参与继承,加
final是冗余且编译不通过的 - 构造器不能用
final修饰(语法错误) - 接口的 default 方法,final 类不能“重写”,但可以自己提供同名方法来实现(这属于实现,不是覆盖)
实际影响和常见误区
使用 final 类会带来一些间接约束:
- CGLIB 等基于继承的动态代理失效(得改用接口代理)
- 旧版 Mockito 模拟 final 类需特殊配置(如 mockito-inline)
- 误以为 “final 类 = 不可变类”——其实 final 只锁住继承,不锁字段状态;
final class A { String data = "x"; }中的data依然可变,要不可变还得配合final字段 + 不可变对象设计
它本质是一种设计契约:这个类已封闭,行为必须稳定,你不该、也不能靠继承去定制它。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











