Java异常处理执行顺序为:无异常时执行try→finally;有异常时匹配catch→finally;finally几乎总执行,但System.exit、线程强制中断或致命错误时例外;finally中return会覆盖try/catch的返回值。

Java里异常处理的执行顺序由try、catch、finally三者之间的控制流规则决定,不是简单按代码位置从上到下执行——尤其当异常发生、return存在或finally里有return时,行为容易出人意料。
异常未抛出时的执行顺序
没有异常发生,try块正常执行完,跳过所有catch,再执行finally(如果存在),最后继续后续代码。
-
try中无return:按顺序走完try→finally -
try中有return:先计算return表达式的值(比如return i++会先取当前i值),暂存返回值,然后进入finally;finally执行完,再真正返回 -
finally里不能改变已确定的返回值(基本类型或不可变对象),但能修改可变对象的内容(如StringBuilder)
异常被catch捕获时的流程
异常在try中抛出后,立即中断当前执行,逐个匹配catch块(按声明顺序,且子类优先于父类),匹配成功后执行对应catch块,之后进入finally(无论catch是否含return)。
- 若
catch块末尾有return,同样先暂存返回值,再进finally - 若
catch中重新抛出异常(throw e),finally仍会执行,然后异常向上冒泡 - 多个
catch只执行一个,匹配后不再检查后面的catch
finally一定会执行吗?什么情况下不走finally
绝大多数情况下finally都会执行,但有三个明确例外:
立即学习“Java免费学习笔记(深入)”;
- JVM直接退出:
System.exit(0)在try或catch中调用,finally被跳过 - 线程被强制中断(如
Thread.stop(),已废弃但理论上存在) -
try或catch中发生了致命错误(如OutOfMemoryError),且JVM选择不执行finally(实际中极少见,不依赖此行为)
注意:return、break、continue、正常结束、异常抛出——这些都不影响finally执行。
finally里写return会覆盖try/catch的返回值
这是最易踩坑的点:finally中的return会直接终结方法,丢弃try或catch中已准备好的返回值。
public static int test() {
try {
return 1;
} catch (Exception e) {
return 2;
} finally {
return 3; // 实际返回3,1和2都被忽略
}
}
同理,如果finally里抛出异常,也会压制try/catch中的异常或返回逻辑。因此,finally中应避免return和显式throw,仅用于资源清理(如close())。
真正需要关注的是finally对返回值的“劫持”能力,以及它在各种return路径下的介入时机——这些细节在重构或调试资源泄漏、状态不一致问题时,往往就是关键线索。










