Understanding the Execution and Return Values of Java finally Blocks
This article examines when Java's finally block executes, explores cases where it may be skipped, analyzes its interaction with return statements and exceptions, and demonstrates how return values are affected through multiple code examples.
1. Introduction
Because an interview question about finally revealed gaps in the author's knowledge, this article investigates the execution timing and return‑value behavior of Java's finally block.
2. Does finally always execute?
Answer: No. Two situations are presented where the finally block is not run.
2.1 Return before the try block
public class TryCatchTest {
private static int total() {
int i = 11;
if (i == 11) {
return i;
}
try {
System.out.println("执行try");
} finally {
System.out.println("执行finally");
}
return 0;
}
public static void main(String[] args) {
System.out.println("执行main:" + total());
}
}Output:
执行main:112.2 Exception before the try block
public class TryCatchTest {
private static int total() {
return 1 / 0;
try {
System.out.println("执行try");
} finally {
System.out.println("执行finally");
}
return 0;
}
public static void main(String[] args) {
System.out.println("执行main:" + total());
}
}Output:
执行main:1/0 (exception thrown before finally runs)Conclusion: If the program never reaches the try block, the finally block is naturally not executed.
Even when the try block runs, the finally block is not guaranteed in extreme cases such as calling System.exit() inside the try block.
public class TryCatchTest {
private static int total() {
try {
System.out.println("执行try");
System.exit(0);
} catch (Exception e) {
System.out.println("执行catch");
} finally {
System.out.println("执行finally");
}
return 0;
}
public static void main(String[] args) {
System.out.println("执行main:" + total());
}
}Output:
执行tryThus, when the try block completes normally or throws an exception, the finally block usually runs, but JVM termination or a return before entering try can skip it.
3. Timing of finally execution
In a normal case, finally runs **before** the return value of the try block is handed back to the caller.
public class TryCatchTest {
private static int total() {
try {
System.out.println("执行try");
return 11;
} finally {
System.out.println("执行finally");
}
}
public static void main(String[] args) {
System.out.println("执行main:" + total());
}
}Output:
执行try
执行finally
执行main:11When an exception is caught, finally also runs before the catch block's return.
public class TryCatchTest {
private static int total() {
try {
System.out.println("执行try");
return 1 / 0;
} catch (Exception e) {
System.out.println("执行catch");
return 11;
} finally {
System.out.println("执行finally");
}
}
public static void main(String[] args) {
System.out.println("执行main:" + total());
}
}Output:
执行try
执行catch
执行finally
执行main:11Therefore, finally executes before any return that originates from the try or catch block.
4. Return values inside finally
4.1 finally without its own return
Even if finally modifies a variable, the original return value captured from try is still returned.
public class TryCatchTest {
private static int total() {
int i = 0;
try {
System.out.println("执行try:" + i);
return i;
} finally {
++i;
System.out.println("执行finally:" + i);
}
}
public static void main(String[] args) {
System.out.println("执行main:" + total());
}
}Output:
执行try:0
执行finally:1
执行main:0The method returns 0 because the return value was captured before finally changed i .
4.2 finally with its own return
If finally contains a return , that value overrides any previous return.
public class TryCatchTest {
private static int total() {
try {
System.out.println("执行try");
return 1;
} finally {
System.out.println("执行finally");
return 2;
}
}
public static void main(String[] args) {
System.out.println("执行main:" + total());
}
}Output:
执行try
执行finally
执行main:2Another example where both try and finally return values:
public class TryCatchTest {
private static int total() {
int i = 1;
try {
System.out.println("执行try:" + i);
return i;
} finally {
++i;
System.out.println("执行finally:" + i);
return i;
}
}
public static void main(String[] args) {
System.out.println("执行main:" + total());
}
}Output:
执行try:1
执行finally:2
执行main:2These examples show that when a return appears in finally , the method's overall return value becomes the one from finally . If finally lacks a return , the value captured earlier (from try or catch ) is returned.
Source: juejin.im/post/5ec2993fe51d45209d437387
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.