Try-Catch-Finally-Return Clarification

Try-catch-finally-return clarification

If the return in the try block is reached, it transfers control to the finally block, and the function eventually returns normally (not a throw).

If an exception occurs, but then the code reaches a return from the catch block, control is transferred to the finally block and the function eventually returns normally (not a throw).

In your example, you have a return in the finally, and so regardless of what happens, the function will return 34, because finally has the final (if you will) word.

Although not covered in your example, this would be true even if you didn't have the catch and if an exception were thrown in the try block and not caught. By doing a return from the finally block, you suppress the exception entirely. Consider:

public class FinallyReturn {
public static final void main(String[] args) {
System.out.println(foo(args));
}

private static int foo(String[] args) {
try {
int n = Integer.parseInt(args[0]);
return n;
}
finally {
return 42;
}
}
}

If you run that without supplying any arguments:

$ java FinallyReturn

...the code in foo throws an ArrayIndexOutOfBoundsException. But because the finally block does a return, that exception gets suppressed.

This is one reason why it's best to avoid using return in finally.

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

Understanding try catch finally with return and value that it returns

Just before returning from the main block, the JVM has to make sure the finally block is executed, so it does that. The idea is to execute the finally block and then come back and execute the return statement from the main block. But if you have a return statement in the finally block, then it will be executed when the finally block is executed... which means that control never returns to the main block to complete the return statement.

  1. The JVM encounters the return statement in the main block. It pauses execution of the main block and checks for a finally clause.
  2. It executes the finally clause in its entirety, including its return statement.
  3. It never thus gets to complete the try block.

Note, however, that the try block's return expression is evaluated and then discarded. This is important if it has side effects. So if your main block has return i++ then this will have no effect on the return value but i will still get incremented. (Thanks to Dirk for pointing this out.)

Java try-finally return design question

Technically speaking, the return in the try block won't be ignored if a finally block is defined, only if that finally block also includes a return.

It's a dubious design decision that was probably a mistake in retrospect (much like references being nullable/mutable by default, and, according to some, checked exceptions). In many ways this behaviour is exactly consistent with the colloquial understanding of what finally means - "no matter what happens beforehand in the try block, always run this code." Hence if you return true from a finally block, the overall effect must always to be to return true, no?

In general, this is seldom a good idiom, and you should use finally blocks liberally for cleaning up/closing resources but rarely if ever return a value from them.

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

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.

Is it bad practice to return from within a try catch finally block?

No, it's not a bad practice. Putting return where it makes sense improves readability and maintainability and makes your code simpler to understand. You shouldn't care as finally block will get executed if a return statement is encountered.

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;


Related Topics



Leave a reply



Submit