Java 中的 finally 是否总是执行?完整代码解析

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Java 中的 finally 块:神话、现实与陷阱

\n\n

每位 Java 开发者,从新手到资深专家,迟早都会遇到 finally 块。教科书上写着:“无论是否发生异常,该块都会执行。” 听起来像是一个铁定的保证,对吧?但让我们深入幕后看看。

\n\n

在 StackOverflow 上,问题 “Does a finally block always get executed in Java?” 获得了数千次浏览和数百条评论。经验丰富的程序员争论不休,新手感到困惑,而实际案例表明:“总是”并非绝对真理。在本文中,我们将分析所有场景,编写真实代码,并查明 finally 何时可能让你失望。

\n\n

finally 如何工作?基本示例

\n\n

首先,经典用法。finally 块用于释放资源:关闭文件、数据库连接、套接字。它在 try(以及发生异常时的 catch)之后执行,但在控制权离开方法之前。

\n\n
public class FinallyDemo {\n    public static void main(String[] args) {\n        try {\n            System.out.println("在 try 内部");\n            int result = 10 / 2; // 一切正常\n        } catch (ArithmeticException e) {\n            System.out.println("捕获到异常:" + e.getMessage());\n        } finally {\n            System.out.println("finally 块已执行!");\n        }\n        System.out.println("程序继续...");\n    }\n}
\n\n

输出:

\n
在 try 内部\nfinally 块已执行!\n程序继续...
\n\n

一切都在预料之中。但如果 try 中发生了一个未被捕获的异常,会发生什么?

\n\n
public class FinallyWithUncaught {\n    public static void main(String[] args) {\n        try {\n            System.out.println("尝试除以零...");\n            int result = 10 / 0; // 异常!\n        } finally {\n            System.out.println("Finally 在异常向上传播之前执行");\n        }\n        // 这一行将不会执行\n        System.out.println("这一行不会被打印");\n    }\n}
\n\n

输出会让新手惊讶:

\n
尝试除以零...\nFinally 在异常向上传播之前执行\nException in thread "main" java.lang.ArithmeticException: / by zero\n    at FinallyWithUncaught.main(FinallyWithUncaught.java:5)
\n\n

finally 块执行了,尽管异常未被处理。正是这种行为催生了“总是”的神话。但让我们深入挖掘。

\n\n

finally 何时不执行?真实场景

\n\n

至少有三种情况下 finally 可能不会执行。记住它们——这将为你节省数小时的调试时间。

\n\n

1. System.exit() — 紧急终止 JVM

\n\n

最著名的案例。如果在 try 块中调用 System.exit(0),JVM 会立即终止,finally 不会执行。

\n\n
public class FinallyAndExit {\n    public static void main(String[] args) {\n        try {\n            System.out.println("开始工作...");\n            System.exit(0); // JVM 在此处终止\n        } finally {\n            // 这段代码不会执行!\n            System.out.println("你以为我会执行?其实不会!");\n        }\n    }\n}
\n\n

输出:

\n
开始工作...
\n\n

为什么?因为 System.exit() 在操作系统层面停止了虚拟机。这不是异常——这是“死亡”命令。finally 块根本来不及执行。

\n\n
\n 重要提示: 如果你在代码中使用 System.exit(),请停止。这是一种不良风格。如需结束程序,请使

博客

书籍推荐