final关键字约束变量引用不可重绑定,而非对象内容不可变;修饰基本类型时值固定,修饰引用类型时仅锁定地址;final方法禁止重写以保障契约;final类禁止继承;final字段在构造器中初始化可提供happens-before保证。
final 关键字不是为了“让对象不可变”,而是为了禁止重绑定——它约束的是变量(引用)本身,不是所指向的对象内容。
final 修饰变量:只允许赋值一次,但不等于对象不可变
这是最容易误解的一点。声明 final List list = new ArrayList(); 后,list 引用不能再指向别的 ArrayList,但 list.add("x") 完全合法。
-
final变量在初始化后无法再被重新赋值(编译期检查) - 如果变量类型是基本类型,值确实固定;如果是引用类型,仅锁定引用地址,不冻结堆上对象的状态
- 想真正实现不可变容器,得用
Collections.unmodifiableList()或ImmutableList.of()(Guava)这类封装逻辑
final 方法:防止子类覆盖,保障契约一致性
当一个方法被标记为 final,比如 public final String toString(),子类无法重写它。这不是为了“性能优化”(JVM 早期可能有内联收益,现在已不依赖此),而是明确表达设计意图:该行为是类协议的一部分,不容篡改。
- 常见于模板方法模式中的钩子方法被禁用时,或安全敏感操作(如
java.lang.String.hashCode()) - 注意:
final方法仍可被子类继承和调用,只是不能重定义逻辑 - 若父类方法本就
private或static,加final没有意义(语法允许但无实际效果)
final 类:彻底封死继承链,强制组合优于继承
声明 final class StringUtils 后,任何类都无法 extends StringUtils。Java 标准库大量使用这一设计,如 String、Integer、LocalDateTime。