目录

一、"无论是否找到匹配"的三种场景

场景 1:异常被捕获(找到匹配)

场景 2:异常未被捕获(没找到匹配,向上抛)

场景 3:没有发生异常(try 正常完成)

二、"在该方法结束之前执行"的深层含义

情况 A:方法有 return

情况 B:异常要向上抛出

三、为什么说"基本正确"而非"绝对"?

四、工程意义


是的,这条规则在 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 的执行机制:

  1. 检测到方法需要退出(return 或抛异常)

  2. 暂停退出动作

  3. 查找并执行 finally 块

  4. 恢复退出动作(return 或抛异常)

三、为什么说"基本正确"而非"绝对"?

之前提到过的极端情况(在前面讨论中已涉及),finally 不会执行:

  1. System.exit(0):直接杀死 JVM 进程

  2. Runtime.halt():强制终止

  3. 守护线程被强制终止

  4. JVM 崩溃(如 OutOfMemoryError 导致 JVM 不稳定)

  5. 物理断电、操作系统 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 都会先执行。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐