题目重点:分别解释 final 变量、方法与类,并讨论不可变对象和安全发布。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- final 的语义与对象不可变性分开;并发可见性需同时考虑正确构造和发布。
解题路线
- final 局部变量或字段只能按初始化规则赋值,引用不能重新指向别的对象;被引用对象内部仍可能变化。
- final 方法禁止子类重写,final 类禁止继承。它们约束扩展点,不表示所有操作无副作用。
- 真正不可变对象需要字段策略、防御性复制、不泄漏内部可变引用及构造时不逃逸 this。集合的只读视图也可能反映底层修改。
- final 字段具有特定初始化安全语义,但不能把含可变状态的对象自动变成线程安全对象;后续状态仍需同步。
手动走一遍
final List<String> xs 仍能 add;把 xs 赋给另一个列表则不允许。返回内部数组会让调用方修改数据,即使该数组字段声明 final;应返回副本或可证明安全的接口。
规模与取舍
防御性复制 n 个元素需 O(n) 时间和空间;不可变快照的读取与更新成本须结合规模权衡。
易错点与追问
容易失分的边界
- final 引用等于不可变。
- 构造器注册回调使 this 提前逃逸。
- 为了性能删除复制而不检查别名。
继续深挖
- records 是否保证深不可变?
- final 与 volatile 解决的并发问题有什么区别?
技术参考
- Java 并发与 final 字段规范:公开技术语义参考。
