JavaSE基础-Java finally执行机制全解析
·

目录
是的,这条规则在 Java 语言规范中是成立的。 但需要注意"在该方法结束之前执行"这个关键限定(后面会讲极端例外)。
这句话包含三个层面的保证:
一、"无论是否找到匹配"的三种场景
场景 1:异常被捕获(找到匹配)
try {
int a = 1 / 0; // 抛出 ArithmeticException
} catch (ArithmeticException e) {
System.out.println("捕获成功"); // ✅ 执行
} finally {
System.out.println("finally"); // ✅ 必然执行
}
// 后续代码继续执行
场景 2:异常未被捕获(没找到匹配,向上抛)
try {
int a = 1 / 0; // 抛出 ArithmeticException
} catch (NullPointerException e) { // ❌ 类型不匹配,捕获失败
System.out.println("捕获失败"); // 不执行
} finally {
System.out.println("finally"); // ✅ 依然会执行!
}
// ⚠️ 然后 ArithmeticException 继续向上抛给调用者
场景 3:没有发生异常(try 正常完成)
try {
System.out.println("正常代码"); // ✅ 执行
} catch (Exception e) {
System.out.println("不会执行");
} finally {
System.out.println("finally"); // ✅ 依然会执行!
}
关键结论:finally 的执行只与方法是否结束有关,与异常是否被处理无关。
二、"在该方法结束之前执行"的深层含义
这指的是:finally 块在方法"真正退出"前的最后一刻执行。
情况 A:方法有 return
public int test() {
try {
return 10; // 准备返回,但先挂起
} finally {
System.out.println("先执行我"); // ✅ 在 return 10 之前执行
}
}
情况 B:异常要向上抛出
public void test() throws Exception {
try {
throw new Exception("错误"); // 准备抛出,但先挂起
} finally {
System.out.println("先执行我"); // ✅ 在异常抛给上层之前执行
}
// 然后才抛出 Exception 给调用者
}
JVM 的执行机制:
-
检测到方法需要退出(return 或抛异常)
-
暂停退出动作
-
查找并执行 finally 块
-
恢复退出动作(return 或抛异常)
三、为什么说"基本正确"而非"绝对"?
之前提到过的极端情况(在前面讨论中已涉及),finally 不会执行:
-
System.exit(0):直接杀死 JVM 进程 -
Runtime.halt():强制终止 -
守护线程被强制终止
-
JVM 崩溃(如
OutOfMemoryError导致 JVM 不稳定) -
物理断电、操作系统
kill -9
四、工程意义
这个保证的存在是为了资源释放的可靠性:
Connection conn = null;
try {
conn = dataSource.getConnection();
// 执行 SQL...
} catch (SQLException e) {
log.error("数据库错误", e);
throw new BusinessException(e); // 抛给上层
} finally {
// ✅ 不管上面是正常、捕获、还是继续抛异常,连接一定关闭
if (conn != null) {
conn.close();
}
}
如果没有这个保证,资源泄漏的风险会大大增加。
一句话总结:在 JVM 正常运行的前提下,finally 是方法退出前的"最后一道保险",无论方法是正常返回、捕获异常后返回、还是抛出异常给上层,finally 都会先执行。
更多推荐



所有评论(0)