Java中finally块是否总是会执行?

Java中finally块是否总是会执行?

技术背景

在Java编程中,try-catch-finally 结构是异常处理的重要机制。finally 块通常用于放置无论是否发生异常都需要执行的代码,比如资源的释放等。那么,finally 块是否总是会被执行呢?这是一个在Java开发中常见且需要明确的问题。

实现步骤

正常情况

在正常情况下,finally 块会在 trycatch 代码块执行之后被调用。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Test {

public static void main(String[] args) {
System.out.println(Test.test());
}

public static int test() {
try {
return 0;
}
finally {
System.out.println("something is printed");
}
}

}

输出结果为:

1
2
something is printed
0

特殊情况

finally 块不会被调用的情况有以下几种:

  1. 调用 System.exit()
  2. 调用 Runtime.getRuntime().halt(exitStatus)
  3. JVM 先崩溃。
  4. trycatch 块中出现无限循环(或其他不可中断、不会终止的语句)。
  5. 操作系统强制终止 JVM 进程,例如在 UNIX 系统上使用 kill -9 <pid>
  6. 主机系统死机,例如电源故障、硬件错误、操作系统崩溃等。
  7. finally 块将由守护线程执行,并且在调用 finally 之前所有其他非守护线程都已退出。

示例代码展示 System.exit() 阻止 finally 块执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A {
public static void main(String args[]) {
DataInputStream cin = new DataInputStream(System.in);

try {
int i = Integer.parseInt(cin.readLine());
} catch (ArithmeticException e) {
} catch (Exception e) {
System.exit(0); // 程序在执行 finally 块之前终止
} finally {
System.out.println("Won't be executed");
System.out.println("No error");
}
}
}

finally 块对返回值和异常的影响

如果 finally 块中有返回语句,它将覆盖常规块中的任何其他返回值。示例代码如下:

1
2
3
4
5
6
7
8
public static int getMonthsInYear() {
try {
return 10;
}
finally {
return 12;
}
}

该方法将返回 12。

同样,如果 finally 块中抛出异常,它将覆盖 try 块中抛出的异常。示例代码如下:

1
2
3
4
5
6
7
8
public static int getMonthsInYear() {
try {
return 12;
}
finally {
throw new RuntimeException();
}
}

核心代码

finally 块覆盖返回值示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static int test() {
try {
return printX();
}
finally {
System.out.println("finally trumps return... sort of");
return 42;
}
}

public static int printX() {
System.out.println("X");
return 0;
}

输出结果为:

1
2
3
X
finally trumps return... sort of
42

finally 块不影响原返回值示例

1
2
3
4
5
6
7
8
9
10
public static int test() {
int i = 0;
try {
i = 2;
return i;
} finally {
i = 12;
System.out.println("finally trumps return.");
}
}

输出结果为:

1
2
finally trumps return.
2

最佳实践

  • 避免在 finally 块中使用返回语句,因为这会使代码的逻辑变得复杂,并且可能掩盖 try 块中的返回值。
  • 确保在 finally 块中进行资源的释放操作,如关闭文件、数据库连接等,以避免资源泄漏。

常见问题

为什么 finally 块中的返回值会覆盖 try 块中的返回值?

因为 finally 块的执行优先级较高,当 try 块中的返回值被放置在一边等待 finally 块执行完毕后,如果 finally 块中有返回值,就会使用 finally 块的返回值。

finally 块是否总是会在 try 块之后执行?

不是的,虽然大多数情况下 finally 块会在 try 块之后执行,但在一些特殊情况下,如 JVM 崩溃、调用 System.exit() 等,finally 块可能不会被执行。


Java中finally块是否总是会执行?
https://119291.xyz/posts/2025-05-13.java-finally-block-execution/
作者
ww
发布于
2025年5月13日
许可协议