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.
- The JVM encounters the
return
statement in the main block. It pauses execution of the main block and checks for afinally
clause. - It executes the
finally
clause in its entirety, including itsreturn
statement. - 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
How to Manage Exceptions Thrown in Filters in Spring
Why Java.Util.Optional Is Not Serializable, How to Serialize the Object with Such Fields
Getting Java.Lang.Classnotfoundexception: Org.Apache.Commons.Logging.Logfactory Exception
Run Exe Which Is Packaged Inside Jar File
MAC Osx - Illegalstateexception: the Driver Is Not Executable:
How to Call Getclass() from a Static Method in Java
How to Solve Circular Reference in JSON Serializer Caused by Hibernate Bidirectional Mapping
Streaming Large Result Sets with MySQL
Generating a Jaxb Class That Implements an Interface
Converting Secret Key into a String and Vice Versa
How to Use Jsch for Ssh Key-Based Communication
Combine Multiple Collections into a Single Logical Collection
Preserving Parameter/Argument Names in Compiled Java Classes
CSV Parsing in Java - Working Example
Best Way to Constrain User to Enter a Time in a Jtextfield
How to Get the Filename Without the Extension in Java
Java "Lambda Expressions Not Supported at This Language Level"