final修饰类禁止继承,如Math、String;修饰方法禁止重写但可调用;修饰变量保证引用不可变,非对象不可变;三者共同支撑封装与安全。

final修饰类:禁止继承
被final修饰的类无法被其他类继承,这是最彻底的封装手段。JVM在加载时会直接拒绝子类的extends尝试,编译期就报错。
典型场景包括工具类(如java.lang.Math)、安全敏感类(如java.lang.String),防止子类篡改核心行为。
- 不能有子类,也就不能重写任何方法,哪怕该方法本身没加
final - 不影响内部是否含
static或private成员 - 与
sealed不同,它不提供允许列表,是全封闭
final修饰方法:禁止重写
final加在方法上,表示该方法可在子类中被调用,但不允许被重写。注意:这和private方法效果不同——private方法根本不可见,而final方法可见但锁定实现。
常见于模板方法模式中的钩子方法、性能关键路径(JIT可能内联优化)、或逻辑必须保持一致的校验方法。
立即学习“Java免费学习笔记(深入)”;
- 子类仍可继承并调用该方法,只是不能用
@Override覆盖 - 若父类方法是
final,子类声明同名方法属于**新定义**,不是重写(会导致隐藏而非多态) - 接口中不能使用
final修饰方法(Java 8+ 接口只允许default、static、private)
final修饰变量:初始化后不可再赋值
对变量而言,final约束的是“引用不可变”,不是“对象不可变”。基本类型值固定;引用类型则地址固定,但其指向对象的内部状态仍可修改。
必须在声明时、构造器中或实例/静态初始化块里完成赋值,否则编译报错:variable xxx might not have been initialized。
- 局部
final变量需在声明处或首次使用前显式赋值 - 成员
final变量不能靠默认值(如0、null),必须主动初始化 -
final List合法,但list = new ArrayList(); list.add("x")没问题,list = new ArrayList();才会报错
final与不可变性的常见误解
很多人以为final = 不可变对象,其实它只保证变量绑定关系不变。真正实现不可变类,还需满足:私有字段、无修改方法、构造器防御性拷贝、子类不可继承(即类也要final)。
比如String是不可变类,靠的是字段final char[] value + 构造时拷贝 + 所有方法返回新实例,三者缺一不可。
- 仅用
final修饰字段,不阻止通过反射修改(Field.setAccessible(true)) - 序列化/反序列化可能绕过
final字段初始化逻辑,需配合readObject自定义 - 在lambda中捕获
final或“ effectively final ”变量,本质是编译器生成的隐式副本,不是共享引用








