final 的核心是向调用方承诺不可变性,约束实现者并影响使用者对生命周期和线程安全的预期;它强制表达设计契约,而非仅语法限制。
final 在 Java 面向对象编程中,核心作用不是“阻止继承”或“禁止修改”,而是**向调用方承诺不可变性**——这个承诺既约束实现者,也影响使用者对对象生命周期和线程安全的预期。
为什么 final 修饰类不能被继承?
这不是语法限制的副作用,而是设计契约的强制表达:一旦声明 final class StringUtils,就表示该类的全部行为(包括所有 public 和 protected 方法)已被视为完整、稳定、不可扩展的语义单元。JVM 层面会跳过虚方法表查找优化,但更重要的是,它堵死了子类通过重写方法篡改其不可变契约的可能。
常见误用场景:
- 为“防止别人乱继承”而把工具类加
final,却没封住所有构造器(比如漏掉private构造器),导致仍可通过反射实例化 - 把
final当访问控制用,以为能替代private或package-private,结果暴露了不该暴露的字段
final 字段 ≠ 对象内容不可变
这是最常踩的坑。final List items = new ArrayList(); 只保证 items 引用不指向别处,但 items.add("x") 完全合法——final 不递归冻结对象内部状态。
立即学习“Java免费学习笔记(深入)”;