Fundamentals 9 min read

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.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Understanding the Execution and Return Values of Java finally Blocks

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:11

2.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:

执行try

Thus, 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:11

When 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:11

Therefore, 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:0

The 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:2

Another 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:2

These 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

Javaexception handlingcode examplesfinallyreturn value
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.