java: try finally blocks execution [duplicate] - java

This question already has answers here:
Does a finally block always get executed in Java?
(51 answers)
Strange finally behaviour? [duplicate]
(7 answers)
Closed 9 years ago.
I am confused about the try-finally execution when there exists return; in the try block. In my understanding, the finally block will always be executed, i.e. before returning to the calling method. While considering the following simple code:
public class TryCatchTest {
public static void main(String[] args){
System.out.println(test());
}
static int test(){
int x = 1;
try{
return x;
}
finally{
x = x + 1;
}
}
}
The result printed is actually 1. Does this mean the finally block is not executed? Can anyone help me with it?

When you return from try block, the return value is stored on the stack frame for that method. After that the finally block is executed.
Changing the value in the finally block will not change the value already on the stack. However if you return again from the finally block, the return value on the stack will be overwritten, and the new x will be returned.
If you print the value of x in finally block, you will get to know that it is executed, and the value of x will get printed.
static int test(){
int x = 1;
try{
return x;
}
finally{
x = x + 1;
System.out.println(x); // Prints new value of x
}
}
Note: In case of a reference value being returned, the value of reference is stored on the stack. In that case, you can change the value of object, using that reference.
StringBuilder builder = new StringBuilder("");
try {
builder.append("Rohit ");
return builder;
} finally {
// Here you are changing the object pointed to by the reference
builder.append("Jain"); // Return value will be `Rohit Jain`
// However this will not nullify the return value.
// The value returned will still be `Rohit Jain`
builder = null;
}
Suggested Read:
JVM Specs - Frames

The finally block is executed. The local variable is incremented. But the value of that local variable has already been copied for the return value.
From the Java Language Specification, 14.17: The return statement:
A return statement with an Expression attempts to transfer control to the invoker
of the method that contains it; the value of the Expression becomes the value of
the method invocation.
...
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

You are returning x before you exit try. I would do this:
public class TryCatchTest {
public static void main(String[] args) {
System.out.println(test());
}
static int test() {
int x = 1;
try {
do something with x.
} finally {
do something that will happen even in case of error;
x = x + 1;
return x;
}
}
}

Related

Try-Catch-Finally | Understanding of control while executing try-finally block contains return statement

Can anyone please explain me code attached.How the control will transfer from try to finally and how finally will work without return statement.
class TryCatchFinally{
int ID = 0;
public Integer test() {
try {
return this.ID;
} finally {
this.ID = 2;
}
}
public static void main(String ...s) {
TryCatchFinally obj = new TryCatchFinally(); //line 1
System.out.println(obj.test()); //line 2
//line 3
}
}
Actual output is -
0
While executing test() function, I have changed the value of ID in finally as 2. I know if I write the obj.ID at line no#3 in main method output will be 2 for line no#3. I would like to know here, I got result as 0 for line no#2. Why? When finally actually been called here?
The finally block does occur. From the docs tutorial:
This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break.
However the result gets "returned" (The method isn't exited, but the return value is stored temporarily) before the finally block is reached, so at the time of the return statement, ID is still zero.
public Integer test() {
try {
return this.ID; //Still 0 at time of return
} finally {
this.ID = 2; //This still gets executed, but after the return value is stored
}
}
If you print out the ID field after the method:
TryCatchFinally obj = new TryCatchFinally(); //line 1
System.out.println(obj.test());
System.out.println(obj.ID);
Then you get:
0
2

What happen in method after return statement

public class TestReturn {
int i = 0;
public static void main(String[] args) {
TestReturn t = new TestReturn();
System.out.println(t.test());
System.out.println(t.i);
}
private int test() {
return i++;
}
}
output
0
1
My question is,
Since return value of test() is 0, i,e un-incremented, so when i print i why it is incremented. What i know is, return is the exit point of method but from this method i found that there is something happening after returning from method.
So how exactly return works?
Simple.
When you do return i++ i is initially 0. The i++ is called the post-increment and as its name says i will be incremeneted after.
Although i++ returns a value before incrementing, the method finishes this statement before heading back to main. A return won't abruptly stop this statement halfway(evaluating but not incrementing)
So you'll return 0, increment it, and then see 1 when calling System.out.println(t.i);.
Technically, the value of i is stored onto the stack, the class field is incremented, and then the copied-out values of i is returned.
It's not the return that's the problem here, it's your usage of the post-increment operator.
What happens with "return i++;" is that the value of i is returned, then the value is incremented. That's why you get 0 and 1 as the values.
The sequence of actions in executing the statement return i++; is as follows.
Evaluate the expression i++.
a. Take the value of i
b. Increment the variable.
Return the value of the expression produced by step 1.
The evaluation of the expression is completed (including the increment) within the method call ... before the call returns.
Since return value of test() is 0, i,e un-incremented, so when i print i why it is incremented.
As you can see from my explanation above, that is because i was incremented as part of the expression evaluation; step 1b.
If u wanna return 1, give return ++i;
return i++; will first return i, then increment it;
i++ can be imagined as another function like (the syntax not applicable to java tough)-
preIncrementFunction(int &i){
int j = *i;
*i = *i+1;
return j;
}
so, the value getting printed is the un-incremented value of i but the value of i has changed.

Why have a return keyword if you're not returning a value?

As I was reading my AP java book I stumbled upon this section that made no sense to me:
...The getBalance method simply returns the current balance. A return statement obtains the value of a variable and exits the method immediately. The return value becomes the value of the method call expression. The syntax of a return statement is:
return expression;
or
return; // Exits the method without sending back a value
Why would you want to have a return statement and "exit the method without sending back a value" if you could just make it void?
***Note: Sorry if this may be too subjective. I just couldn't understand the point and the book doesn't explain it.
The return keyword doesn't need to be at the end. For example:
public static void print42(int[] numbers) {
for(int i=0; i<numbers.length; i++) {
if (numbers[i] == 42) {
System.out.println("has 42");
return;
}
}
System.out.println("no 42");
}
It can't just use a break, as that would print both strings.
This is kind of subjective. I'm old school, I believe in one entry and exit point for all methods/functions, but...
If you have a method with a void return type and if you had reached a point in your logic which would dictate that no further processing should take place, you could call return; to force the execution to return to the calling method at this point, foregoing any further execution of the method.
It would be the same as using something like return x; in the middle of a method body that had an expected return type (of whatever x is)
It's a little like using break to break out of a loop prematurely, except you're breaking out of the method before the execution gets to the end.
There are some situations where once you've verified something inside a void function, it makes sense to exit it immediately. For example:
public static void checkIfStringInList(List<String> searchList, String findString) {
for( String thisSearchString : searchList ) {
if( findString.equals(thisSearchString) )
return;
}
throw new Exception("String " + findString + " not found in list");
}
A method declared as void can exit with a return; this is just a shortcut for early termination. A method with a non-void return type must return a value of the right type, you can not have a method return "nothing" if it has a non-void return type.
If your method has a void return type, then the return statement is optional. You might want to use it anyway if, for instance, you wanted to stop execution in certain cases.
If the return type is not void, then using return; without an argument will give you a compile error.
In java if a method has a return type in its signature, you must return an object of that type or null before exiting the method.
for example
public A foo(boolean val){
A obj=null;
if (val){
obj=new A();
obj.setSomeAttribute();
}
return obj;
}
You can not compile source code if you just code "return;"

Which will be returned in a program

I was wondering what will be returned in a java program when you have multiple returns in a program.
private int numberReturner()
{
if (a) return a;
else if (b) return b;
for (int i = 1; i < board.size()-1; i++)
{
if (c) return c;
}
return d;
}
So lets say a is true, (it should return a), but wouldn't it return d because that is the final line of code in the whole program? Why is this so?
Sorry if I worded this a bit strangely...
Once any 'return' statement is encountered the method will exit execution and return that value.
That method will return d only if no other return statement is encountered before reaching that last line.
Normally, the first "return" encountered will be the one returned. But if there is a "return" statement encountered in a finally block, the "return" in the finally block will be returned.
e.g.
private int m1(){
try{
return 1;
}finally{
return 2; //this will be returned instead
}
}
If you've already "returned" you are never going to hit the subsequent returns.
The method returns a because the return statement exits from the current method, and control flow returns to where the method was invoked. Please read more about different branching keywords in Java tutorial. http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
Once a return statement is executed the method ends and if it is not void the return value is returned.
I know only one exception to this rule, and you have it with the finally statement.
Take this example:
public static void main(String[] args) {
System.out.println(test());
}
private static int test() {
try {
return 1;
} finally {
return 2;
}
}
in this case test() returns 2, because the finally statement in this case is always executed before exit the method.
The current execution thread will leave a method the first time it encounters a return statement (the notable exception to this rule is with try...finally blocks, where, once a return is encountered, the finally{...} block executes before leaving the method.

end the method that call this method

Is there a way to end the method that calls on the method that the code is in. Let me explain if you have some code like this.
int value;
value = method();
value = 3;
If I got it work like I want then the execution of the code would end on line 2 and line 3 would never be executed. basically it would be like there was a return between line 2 and 3. Is is something like this possible with Java?
Edit: Ok i think a lot of people have misunderstood me. The code that end the code on in this method on line 2 should be inside of method() and it should not be possible to avoid this outside this method if it's call inside of a try for example.
Your example is a bit abstract, a real one might result in better answers. In general though there are two ways this is normally achieved:
Return a special value e.g. -1
int method() {
if (/* something is wrong */) {
return -1;
}
// Process as normal and return real value
}
...
int value;
value = method();
if (value == -1) {
value = 3;
}
Throw an exception in method()
int method() throws IllegalStateException {
if (/* something is wrong */) {
throw new IllegalStateException();
}
// Process as normal and return real value
}
...
int value;
try {
value = method();
} catch (IllegalStateException e) {
value = 3;
}
You can terminate the current program / JVM with System.exit
java.lang.System.exit(0 /* Status */ );
If you don't want to exit then you have to use return.
in a void method do
int value;
value = method();
return;
Or if method has the same return signature as the current method
int value;
return value = method();
Add if condition value=youexpected return;

Categories