当前位置: 首页 > news >正文

孤舟笔记 基础篇十五 finally 不是永远执行的吗?这些情况它真的不会执行

文章目录

    • 一、先说结论:finally 几乎一定执行,但不是绝对
    • 二、正常情况:finally 确实很靠谱
    • 三、不执行的情况:finally 也无力回天
      • 1. System.exit()——JVM 关机,谁也拦不住
      • 2. 无限循环/死锁——永远到不了 finally
      • 3. 守护线程——JVM 退出时直接被抛弃
      • 4. kill -9——操作系统直接砍进程
    • 四、finally 的另一个坑:return 覆盖
    • 五、回到全貌:一图记住
    • 六、回答技巧与点评
      • 标准回答
      • 加分回答
      • 面试官点评

个人网站

面试官问你:"finally 语句块一定会执行吗?"你脱口而出:"一定!"面试官笑了:“确定?”

你开始慌了。不是叫 finally 吗?finally 不就是"最终"的意思吗?最终执行,那不是一定的吗?

还真不是。finally 有几种情况真的不会执行,而且其中一些你可能在工作中已经踩过坑,只是没意识到。

一、先说结论:finally 几乎一定执行,但不是绝对

情况finally 是否执行
正常执行 try✅ 执行
try 中抛异常✅ 执行
try 中 return✅ 执行(return 前先执行 finally)
try 中有 return,finally 也有 return✅ 执行,但 finally 的 return 会覆盖 try 的
System.exit()❌ 不执行,JVM 直接关了
无限循环/死锁❌ 不执行,永远到不了 finally
守护线程中 JVM 退出❌ 不执行,线程被直接干掉
强行杀进程(kill -9)❌ 不执行,操作系统层面干掉了

一句话记住:finally 挡得住异常,挡不住 JVM 关机。

二、正常情况:finally 确实很靠谱

先看 finally 的"基本盘"——绝大多数情况下它确实会执行:

// 情况1:正常执行try{System.out.println("try");}finally{System.out.println("finally");// ✅ 执行}// 情况2:抛异常try{thrownewException("炸了");}finally{System.out.println("finally");// ✅ 执行}// 情况3:try 里有 returntry{return;}finally{System.out.println("finally");// ✅ 执行!return 之前先跑 finally}

这三种情况覆盖了日常开发的 99%,所以很多人形成了"finally 一定执行"的印象。但面试考的就是那 1%。

三、不执行的情况:finally 也无力回天

1. System.exit()——JVM 关机,谁也拦不住

try{System.out.println("try");System.exit(0);// JVM 直接退出}finally{System.out.println("finally");// ❌ 不会执行!}

System.exit()是拔电源级别的操作——JVM 都关了,还执行什么 finally?就像你正要锁门出门,结果房子塌了,门还锁个啥。

这也是为什么说 finally 挡不住 JVM 关机。System.exit(0)是正常退出,System.exit(1)是异常退出,不管哪个,JVM 都直接走人。

2. 无限循环/死锁——永远到不了 finally

try{while(true){// 死循环// 永远出不去}}finally{System.out.println("finally");// ❌ 永远执行不到}

finally 的前提是 try 块结束(不管是正常结束还是异常结束)。如果 try 根本结束不了,finally 自然没机会上场。就像排队等下班打卡,但你永远在加班,那下班卡永远打不上。

3. 守护线程——JVM 退出时直接被抛弃

Threaddaemon=newThread(()->{try{System.out.println("守护线程:try");}finally{System.out.println("守护线程:finally");// ❌ 可能不执行}});daemon.setDaemon(true);// 设置为守护线程daemon.start();// 主线程结束后 JVM 退出,守护线程的 finally 不会执行

守护线程是给用户线程"打辅助"的。当所有用户线程结束,JVM 就要退出,守护线程会被直接干掉,不管你 finally 里写了什么。所以千万别在守护线程的 finally 里做资源释放,靠不住。

4. kill -9——操作系统直接砍进程

这个不用代码演示了。你在服务器上kill -9强杀 Java 进程,操作系统直接回收内存,JVM 连善后的机会都没有,finally 自然不会执行。

四、finally 的另一个坑:return 覆盖

finally 不止"执不执行"有坑,"怎么执行"也有坑:

publicstaticinttest(){try{return1;}finally{return2;// 👈 finally 的 return 覆盖了 try 的 return}}// 返回 2,不是 1

千万不要在 finally 里写 return!它不仅会覆盖 try 的返回值,还会吞掉 try 里的异常:

publicstaticinttest(){try{thrownewRuntimeException("炸了");}finally{return2;// 👈 异常被吞了!调用方完全不知道出过错}}// 返回 2,异常消失了,调用方无感知

finally 里的 return 就像开会时领导最后总结——不管你前面说了啥,领导说的才是最终结论,你的话全白说。

五、回到全貌:一图记住

finally 执行情况 ├── ✅ 一定执行:正常、异常、try 有 return └── ❌ 不执行: ├── System.exit() → JVM 关机 ├── 死循环/死锁 → 永远到不了 ├── 守护线程 JVM 退出 → 直接被抛弃 └── kill -9 → 操作系统强杀 finally 的坑 ├── finally 里的 return 会覆盖 try 的 return └── finally 里的 return 会吞掉 try 的异常 口诀:finally 挡得住异常,挡不住关机; finally 别写 return,写了覆盖又吞异常。

六、回答技巧与点评

标准回答

finally 语句块在绝大多数情况下会执行,包括 try 正常结束、抛异常、甚至 try 中有 return 时都会在 return 之前执行 finally。但在以下情况不会执行:调用了 System.exit() 导致 JVM 退出、try 中存在无限循环或死锁导致永远无法退出、守护线程中 JVM 退出时线程被直接终止、操作系统强杀进程。另外需要注意,finally 中不要写 return 语句,它会覆盖 try 的返回值并吞掉异常。

加分回答

  1. 提到 try-with-resources:Java 7 引入的 try-with-resources 比 finally 关闭资源更安全,因为它会保留原始异常,不会被 finally 中的异常覆盖
  2. 提到 finally 执行时机:finally 在 try 的 return 之前执行,但 return 的值在 finally 执行前就已经确定了(除非 finally 修改了引用类型的字段)
  3. 提到实际建议:资源释放优先用 try-with-resources,别在 finally 里写 return,守护线程的清理逻辑别放 finally

面试官点评

这道题是经典坑题,考的是你对 JVM 运行机制的理解。"finally 一定执行"是大多数人脱口而出的答案,但能说出 System.exit() 和守护线程两种不执行的情况,就说明你比一般人深了一层。如果能再提到 finally 中 return 的坑和 try-with-resources 的最佳实践,面试官会认为你不仅懂原理,还知道怎么避坑,这是加分项。

原文阅读


内容有帮助?点赞、收藏、关注三连!评论区等你 💪

http://www.jsqmd.com/news/704715/

相关文章:

  • 神经网络联合建模:分类回归任务实战指南
  • 【无人机动态路径规划】镜像速度粒子群算法结合动态窗口的无人机复杂山地模型威胁路径规划和动态避碰【含Matlab源码 15378期】
  • 保姆级教程:在Ubuntu 18.04上搞定Gluon-2L6-4L3机械臂的ROS Melodic驱动(含网络配置避坑)
  • 如何用嘎嘎降AI高效处理多篇论文:批量降AI完整操作教程 - 还在做实验的师兄
  • 魔兽世界API开发终极指南:3分钟掌握wow_api完整使用技巧
  • XUnity.AutoTranslator:如何让外语游戏瞬间变成你的母语?
  • 如何快速配置象棋AI:深度学习辅助的完整指南
  • go: Memento Pattern
  • 【LeetCode刷题日记】1047:双栈法与双指针法巧妙消除相邻重复字符
  • 量子计算中的状态准备技术:原理、方法与工程实践
  • 降AI工具会不会影响论文查重率:原理分析和实测数据深度解读 - 还在做实验的师兄
  • Windows系统优化终极指南:Chris Titus Tech WinUtil一键搞定所有系统管理
  • 企业级XPath定位工具架构设计与性能优化实践
  • Stable Diffusion本地部署与AI图像生成实战指南
  • Windows系统优化终极指南:Chris Titus Tech WinUtil工具完整实战教程
  • AI率检测阈值是怎么设定的:各高校和期刊标准差异解读 - 还在做实验的师兄
  • Snap.Hutao原神工具箱终极指南:10个提升游戏效率的实用技巧
  • 【限时解禁】VS Code Copilot Next 架构设计图自动化套件:1键生成符合CNCF云原生标准的双向可追溯流程图(含GitOps回滚锚点标记)
  • 终极指南:如何在电脑上流畅控制安卓手机的完整教程
  • 告别U盘文件管理烦恼:智能自动备份工具如何让数据同步变得轻松
  • LLaMA-Factory数据集格式详解与高质量数据构建方法-原理源码解析
  • 如何用3分钟将B站缓存视频转为通用MP4格式?
  • G-Helper:华硕笔记本性能管理的开源革命,3步释放硬件潜能
  • 打卡信奥刷题(3169)用C++实现信奥题 P7912 [CSP-J 2021] 小熊的果篮
  • GRETNA脑网络分析终极指南:5步掌握MATLAB图论计算全流程
  • 为什么不同降AI工具效果差异这么大:技术原理和算法差异深度分析 - 还在做实验的师兄
  • 深度解析Tiled地图编辑器符号链接路径问题的系统解决方案
  • 为什么同一篇论文知网和维普AIGC检测结果不同:平台差异深度解读 - 还在做实验的师兄
  • qmc-decoder终极指南:如何快速解锁QQ音乐加密音频文件?
  • 2026年3月洁净车间不锈钢操作台直销厂家推荐,洁净车间不锈钢操作台/工具柜,洁净车间不锈钢操作台厂商怎么选择 - 品牌推荐师