final锁住的是引用或值的不可变性而非对象状态,finally并非绝对执行且慎用return,finalize已被弃用。

final 修饰符到底锁住什么
final 不是“让对象不可变”,而是“让引用不可再赋值”。常见误解是 final List 后,以为 list.add("x") 会报错——其实完全合法。真正被锁住的只是 list 这个变量名不能再指向另一个 List 实例。
-
final修饰基本类型:值不可变(如final int x = 1;) -
final修饰引用类型:引用地址不可变,但对象内部状态可变(如final StringBuilder sb = new StringBuilder(); sb.append("a");合法) -
final修饰方法:子类不能重写该方法(注意:不影响重载) -
final修饰类:该类不能被继承(如String、Integer)
finally 块不是“总会执行”的保险柜
绝大多数情况下 finally 会执行,但有两个硬性例外:JVM 直接退出(如调用 System.exit(0)),或 线程被强制中断且未恢复(如 Thread.stop(),已废弃但仍有影响)。更隐蔽的问题是:如果 try 或 catch 中有 return,finally 仍会执行——但它可能“覆盖”返回值。
public static int test() {
try {
return 1;
} finally {
return 2; // 这个 return 会生效,test() 总是返回 2
}
}
- 不要在
finally里写return,否则会吞掉原始返回值或异常 - 资源释放逻辑放
finally是合理的,但别在里面抛异常(会掩盖原异常) - JDK 7+ 推荐用
try-with-resources替代手写finally关流
finalize 方法早已被弃用,别再实现它
finalize() 在 JDK 9 被标记为 @Deprecated,JDK 18 彻底移除。它既不保证何时执行,也不保证一定执行,更无法替代显式资源管理。JVM 可能在 OOM 前都来不及触发它,而频繁触发又会拖慢 GC。
- 所有依赖
finalize()清理资源(如关文件、释放 native 内存)的代码都是危险的 - 替代方案:实现
AutoCloseable+try-with-resources,或使用Cleaner(JDK 9+)做异步清理 - 哪怕只是为了兼容旧版,也别在
finalize()里做耗时操作或调用同步方法(易引发死锁)
面试时最容易混淆的三个点
面试官常故意把 final、finally、finalize 放一起问,不是考背诵,而是看你是否踩过坑、有没有生产经验。
立即学习“Java免费学习笔记(深入)”;
-
final字段在构造器中没初始化 → 编译报错variable might not have been initialized -
finally块中修改了基本类型返回值的副本,但没return→ 不影响原返回值(很多人误以为“改了就生效”) - 重写
finalize()却没调用super.finalize()→ 父类资源泄漏(虽然现在不该写,但老代码里真有)
这三个词长得像,但一个管编译期约束,一个管控制流保障,一个管对象销毁钩子——它们之间没有设计上的关联,只是名字碰巧押韵。别被表象带偏。









