Software Engineer · 语言与工程基础

Java final:引用不能重赋值为何不等于对象不可变

分别解释 final 变量、方法与类,并讨论不可变对象和安全发布。

题目重点:分别解释 final 变量、方法与类,并讨论不可变对象和安全发布。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • final 的语义与对象不可变性分开;并发可见性需同时考虑正确构造和发布。

解题路线

  1. final 局部变量或字段只能按初始化规则赋值,引用不能重新指向别的对象;被引用对象内部仍可能变化。
  2. final 方法禁止子类重写,final 类禁止继承。它们约束扩展点,不表示所有操作无副作用。
  3. 真正不可变对象需要字段策略、防御性复制、不泄漏内部可变引用及构造时不逃逸 this。集合的只读视图也可能反映底层修改。
  4. final 字段具有特定初始化安全语义,但不能把含可变状态的对象自动变成线程安全对象;后续状态仍需同步。

手动走一遍

final List<String> xs 仍能 add;把 xs 赋给另一个列表则不允许。返回内部数组会让调用方修改数据,即使该数组字段声明 final;应返回副本或可证明安全的接口。

规模与取舍

防御性复制 n 个元素需 O(n) 时间和空间;不可变快照的读取与更新成本须结合规模权衡。

易错点与追问

容易失分的边界

  • final 引用等于不可变。
  • 构造器注册回调使 this 提前逃逸。
  • 为了性能删除复制而不检查别名。

继续深挖

  • records 是否保证深不可变?
  • final 与 volatile 解决的并发问题有什么区别?

技术参考

✓已复制微信号!