finally总是在return之前执行,但不阻止return生效;若finally含return则覆盖原返回值;仅system.exit()或jvm崩溃时finally不执行。

Java里try-catch-finally的执行顺序不是靠“语句先后”决定的,而是JVM在编译阶段就把finally逻辑“织入”所有可能的出口路径——包括正常结束、异常抛出、return、break、continue等。这种机制保障了finally的强执行性,但也带来了几个关键细节。
finally被插入到每个出口,不是“最后才跑”
JVM不会等try或catch执行完再跳过去执行finally;它在生成字节码时,就将finally块的指令复制并安插在所有可能的控制流终点前。比如:
- try中没异常 → 执行完try最后一行后,直接跳转到finally代码段
- try中抛NullPointerException → 跳过剩余try代码,找到匹配catch,执行完catch最后一行后,再跳转到finally
- try中有return "a" → JVM先缓存返回值"a",强制跳入finally执行,再真正返回
- catch中throw new RuntimeException() → 异常对象创建后,不立即上抛,而是先执行finally,再继续抛出
return和finally共存时,返回值由谁定?
重点不在“谁先写”,而在“谁最终触发方法退出”。规则很明确:
- try或catch里的return只负责“暂存返回值”,不终结方法
- finally若无return,会原样返回那个暂存值
- finally若有return,它会丢弃之前所有暂存值,直接用自己return的值退出方法
- finally若抛异常,也会中断原返回流程,以新异常为准(原返回值或原异常都被覆盖)
这就是为什么阿里巴巴开发手册强制要求:不要在finally中写return——它会让方法行为变得不可预测,且掩盖真实意图。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
finally不执行的唯一情况
表面上“总是执行”,但有且仅有两类例外:
- JVM进程被强制终止,例如调用了System.exit(),此时整个进程退出,finally来不及运行
- 发生致命错误(如OutOfMemoryError导致JVM崩溃),底层已无法调度Java代码
注意:即使try里是死循环、catch里是无限递归、或者finally自己陷入阻塞,只要线程还活着、JVM没退出,finally就一定会被执行。
资源释放为什么要靠finally,而不是catch?
因为catch只处理“已捕获的异常”,而资源泄漏可能发生在多种路径:
- try里没异常,但后续逻辑需要清理(比如打开文件后正常读完)
- try里抛的是未被捕获的异常(比如catch只写Exception,但实际抛了Error)
- try里return了,但忘了关流——没有finally,return会直接跳出,资源永远卡住
所以finally的本质价值,是提供一个与“是否出错”解耦的确定性执行点。现代写法更推荐try-with-resources,它本质是编译器自动帮你生成了带finally的close逻辑,且能正确处理close()自身抛异常的情况(通过addSuppressed)。但理解底层finally机制,才能真正用好它。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










