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 block to be discarded.
Yes, the finally block will be executed even after a return statement in a method. The finally block will always execute even an exception occurred or not in Java. If we call the System.
Yes, we can write a return statement of the method in catch and finally block.
When catch and finally block both return value, method will ultimately return value returned by finally block irrespective of value returned by catch block.
The try
block completes with the execution of the return
statement and the value of s
at the time the return
statement executes is the value returned by the method. The fact that the finally
clause later changes the value of s
(after the return
statement completes) does not (at that point) change the return value.
Note that the above deals with changes to the value of s
itself in the finally
block, not to the object that s
references. If s
was a reference to a mutable object (which String
is not) and the contents of the object were changed in the finally
block, then those changes would be seen in the returned value.
The detailed rules for how all this operates can be found in Section 14.20.2 of the Java Language Specification. Note that execution of a return
statement counts as an abrupt termination of the try
block (the section starting "If execution of the try block completes abruptly for any other reason R...." applies). See Section 14.17 of the JLS for why a return
statement is an abrupt termination of a block.
By way of further detail: if both the try
block and the finally
block
of a try-finally
statement terminate abruptly because of return
statements, then the following rules from §14.20.2 apply:
If execution of the
try
block completes abruptly for any other reason R [besides throwing an exception], then thefinally
block is executed, and then there is a choice:
- If the
finally
block completes normally, then thetry
statement completes abruptly for reason R.- If the
finally
block completes abruptly for reason S, then thetry
statement completes abruptly for reason S (and reason R is discarded).
The result is that the return
statement in the finally
block determines the return value of the entire try-finally
statement, and the returned value from the try
block is discarded. A similar thing occurs in a try-catch-finally
statement if the try
block throws an exception, it is caught by a catch
block, and both the catch
block and the finally
block have return
statements.
Because the return value is put on the stack before the call to finally.
If we look inside bytecode, we'll notice that JDK has made a significant optimization, and foo() method looks like:
String tmp = null;
try {
s = "dev"
tmp = s;
s = "override variable s";
return tmp;
} catch (RuntimeException e){
s = "override variable s";
throw e;
}
And bytecode:
0: ldc #7; //loading String "dev"
2: putstatic #8; //storing it to a static variable
5: getstatic #8; //loading "dev" from a static variable
8: astore_0 //storing "dev" to a temp variable
9: ldc #9; //loading String "override variable s"
11: putstatic #8; //setting a static variable
14: aload_0 //loading a temp avariable
15: areturn //returning it
16: astore_1
17: ldc #9; //loading String "override variable s"
19: putstatic #8; //setting a static variable
22: aload_1
23: athrow
java preserved "dev" string from being changed before returning. In fact here is no finally block at all.
There are 2 things noteworthy here:
I change your code a bit to prove the point of Ted.
As you can see in the output s
is indeed changed but after the return.
public class Test {
public String s;
public String foo() {
try {
s = "dev";
return s;
} finally {
s = "override variable s";
System.out.println("Entry in finally Block");
}
}
public static void main(String[] xyz) {
Test obj = new Test();
System.out.println(obj.foo());
System.out.println(obj.s);
}
}
Output:
Entry in finally Block
dev
override variable s
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 s
, 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With