Returning from a Finally Block in Java

Can we use return in finally block

Returning from inside a finally block will cause exceptions to be lost.

A return statement inside a finally block will cause any exception that might be thrown in the try or catch block to be discarded.

According to the Java Language Specification:

If execution of the try block completes abruptly for any other reason
R, then the finally block is executed, and then there is a choice:

   If the finally block completes normally, then the try statement
completes abruptly for reason R.

If the finally block completes abruptly for reason S, then the try
statement completes abruptly for reason S (and reason R is
discarded).

Note: As per JLS 14.17 - a return statement always completes abruptly.

Returning from a finally block in Java

The examples you provided are reason enough to not use flow-control from finally.

Even if there's a contrived example where it's "better," consider the developer who has to maintain your code later and who might not be aware of the subtleties. That poor developer might even be you....

Returning a value from a finally block

The code will never reach finally right?
No, If there is a finally block control will go to finally after try or/and catch

Because in any case finally will always execute. Except as Mike Kobit said System.exit

Thanks Jason C, From JLS 14.17. The return Statement

It can be seen, then, that a return statement always completes abruptly.

The preceding descriptions say "attempts to transfer control" rather than just "transfers control" because if there are any try statements (§14.20) within the method or constructor whose try blocks or catch clauses contain the return statement, then any finally clauses of those try statements will be executed, in order, innermost to outermost, before control is transferred to the invoker of the method or constructor. Abrupt completion of a finally clause can disrupt the transfer of control initiated by a return statement.

From JLS 14.20.2. Execution of try-finally and try-catch-finally

If execution of the try block completes normally, then the finally block is executed, and then there is a choice:

  1. If the finally block completes normally, then the try statement completes normally.
  2. If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S.

So In you code try returns 1, then control goes to finally which returns 3. so return value of function will be 3.

Returning from finally block

The difference from behaviour in Java is because try ... catch ... finally is an expression in Kotlin, not a statement.

The way that a "try-expression" is evaluated, is defined as follows in the specification:

The try-expression evaluation evaluates its body; if any statement in the try body throws an exception (of type E), this exception, rather than being immediately propagated up the call stack, is checked for a matching catch block. If a catch block of this try-expression has an exception parameter of type T:>E , this catch block is evaluated immediately after the exception is thrown and the exception itself is passed inside the catch block as the corresponding parameter. [...]

If there is a finally block, it is evaluated after the evaluation of all previous try-expression blocks

The value of the try-expression is the same as the value of the last expression of the try body (if no exception was thrown) or the value of the last expression of the matching catch block (if an exception was thrown and matched). All other situations mean that an exception is going to be propagated up the call stack, and the value of the try-expression is undefined.

Note: as described, the finally block (if present) is always executed, but has no effect on the value of the try-expression.

So when throwing is true, the try, catch, and finally blocks are all executed, but the value of the try-expression is the value of the last expression in the catch block. This explains the behaviour in both the "explicit" and "implicit" cases.

In the "explicit return" case, return 2 is executed, but the method can't return there - the finally block still has to run! Then return 3 is executed, and now the method returns. Notably, the outer return is never executed. You can delete the outer return and start the method with try { ... and get the same result.

In the "implicit return" case, 2 is evaluated, and no side effects happen since it is just a literal. Then the finally block runs, and 3 is evaluated, and again no side effects happen since it is just a literal. Now we have finished evaluating the whole try-expression, and according to the spec, the value of the expression should be what we evaluated in the catch block - i.e. 2. And now we execute return 2.

Side note: return ... are also expressions, and they have the type of Nothing (the subtype of every type), because they never evaluate to anything. This is why you are able to write return 1 etc as the last line in the try-expression blocks in the "explicit return" case. In that case, the try-expression actually has a type of Nothing, and the outer return is actually returning Nothing. This is fine, because Nothing is a subtype of Int.

Is placing return statement before finally block a good practice?

Putting return in the try or even in the catches is absolutely fine: do whatever is clearest. Take care not to discard too many exceptions though, particularly java.lang.Throwable as doing that can interfere with the workings of the JVM.

Note that if you have a return in the finally block, then the expression in the other return is still evaluated but the result is discarded and the return value in the finally block is returned back to the caller. Because of this, putting a return value in the finally block is discouraged.

try-catch-finally with return after it

The fact that the finally block is executed does not make the program forget you returned. If everything goes well, the code after the finally block won't be executed.

Here is an example that makes it clear:

public class Main {

public static void main(String[] args) {
System.out.println("Normal: " + testNormal());
System.out.println("Exception: " + testException());
}

public static int testNormal() {
try {
// no exception
return 0;
} catch (Exception e) {
System.out.println("[normal] Exception caught");
} finally {
System.out.println("[normal] Finally");
}
System.out.println("[normal] Rest of code");
return -1;
}

public static int testException() {
try {
throw new Exception();
} catch (Exception e) {
System.out.println("[except] Exception caught");
} finally {
System.out.println("[except] Finally");
}
System.out.println("[except] Rest of code");
return -1;
}

}

Output:

[normal] Finally
Normal: 0
[except] Exception caught
[except] Finally
[except] Rest of code
Exception: -1

return in try-catch's finally block in java. Is there any good point in this example?

Is there really any point in adding a finally block here?

The answer to this is a resounding "no": putting a return statement in the finally block is a very bad idea.

I just add the return null inside the catch block, which would execute the same behavior, or am I wrong?

It wouldn't match the original behavior, but that's a good thing, because it would fix it. Rather than returning null unconditionally the way the original code does, the code with the return inside the catch block would return null only on errors. In other words, the value returned in the try branch would be returned to the caller unless there is an exception.

Moreover, if you add return null after the catch block, you would see the correct effect of returning null on exception. I would go even further, and put a single return in the method, like this:

response or = null;
try {
or = //gives it a value
log.info(or.toString());
} catch ( Exception e) {
e.printStackTrace();
}
return or;

The order of return value with try catch finally

This question is closely related, although it returns literals but not variables: Multiple returns: Which one sets the final return value?

In fun1 the return value is set via return a in the catch-block. At that line the value of a is copied into the return value. Changing a later does not change the return value.

In fun2 you have an explicit return in the finally block, so the return value in the finally block is what is returned.

Please read carefully through the answers in the question above for why you should not write code like that.

Another related question is this one: Returning from a finally block in Java

Will modifications to a function's return value in the finally block take effect?

The following things will happen when you will call this method:

  1. The expression, x = x + 1; will increase the value of x by 1 i.e. its value will become 1. Then, throw new Exception(); will be executed and as a result, the control will enter the catch block.
  2. Inside the catch block, x = x + 2; will increase the value of x by 2 i.e. its value will become 3 which is the value that will be returned.
  3. Since finally block is supposed to be executed irrespective of whether an exception is thrown or not, this block will be executed but it won't change the return value. Thus, finally block is useless here. Typically, finally block is used to release resources. Check this to learn more about it.


Related Topics



Leave a reply



Submit