try-finally block clarification [duplicate]
Asked Answered
U

5

5

When I try to execute the following function in Java:

public static int myfunc (int x) {
    try {
        return x;
    } finally {
        x++;
    }       
}
public static void main (String args[]) {
    int y=5,z;
    z = myfunc(y);
    System.out.println(z);
}

The output printed on the console is 5, where as one would expect 6 to be printed. Any idea why?

U answered 21/7, 2015 at 6:15 Comment(7)
return will supersede any other changes. Besides, any changes you make to x won't be seen outside of the method anyway. You many also want to investigate the differences between post and pre incrementsSkirret
@MadProgrammer: Post/pre wouldn't make any difference to the code above.Ator
@T.J.Crowder Not in the code above, but if the OP tried to do something like return x++; in the finally block, then it would ;)Skirret
@MadProgrammer: Yes, but if we're imagining different code from what's in the question, any number of things are applicable.Ator
If you print y it will be 6. ;PPervasive
@T.J.Crowder This is true, but an understand of the concept wouldn't hurt while we're fixing other things ;)Skirret
return: returns control immediately to the caller of its method. And finally: will always be executed. but will wait for its turn :-)Tophole
A
6

...would expect 6 to be printed. Any idea why?

The x++ happens after the value 5 has been read from x. Remember that what follows the return statement is an expression. When the return statement is reached, that expression is evaluated (its value is determined), and then that resulting value is used as the function's return value. So in myfunc, here's the order of what happens:

  1. Enter the try block.
  2. Evaluate the expression x (e.g., get the value of x).
  3. Set that value as the function's return value.
  4. Enter the finally block.
  5. Increment x.
  6. Exit the function using the return value from Step 3.

So as of when we leave the function, even though x is 6, the return value was determined earlier. Incrementing x doesn't change that.

Your code in myfunc is analogous to this:

int y = x;
x++;

There, we read the value of x (just like return x does), assign it to y, and then increment x. y is unaffected by that increment. The same is true for the return value of the function.

It might be clearer with functions: Assuming a foo function that outputs "foo" and returns 5, and a bar function that outputs "bar", then this code:

int test() {
    try {
        return foo();
    }
    finally {
        bar();
    }
}

...executes foo, outputting "foo", then executes bar, outputting "bar", and exits from test with the return value 5. You don't expect the function to wait to call foo until after the finally occurs (that would be strange), and indeed it doesn't: It calls it when it reaches the return foo(); statement, because it evaluates the expression foo(). The same is true of return x;: It evaluates the expression and remembers the result as of that statement.

Ator answered 21/7, 2015 at 6:23 Comment(0)
D
4

Finally block always executes but you returned the value in try block itself. After the value of x returned, x got incremented in finally.

public static int myfunc (int x) {
    try {
        return x;  // returning
    } finally {
        x++;   // now incremented.
    }       
}

Note: Just for testing, if you playing with try-catch-finally, just return in finally (not recommended) and see.

Deformation answered 21/7, 2015 at 6:16 Comment(0)
K
0

Finally is executed no matter what, In this case the value is 5 which returned and then incrementing x.

package qwerty7;

public class Stack {
    public static int myfunc (int x) {
        try {
            return x;
        } finally {
            System.out.println("I'm executing!");
            x++;
        }       
    }
    public static void main (String args[]) {
        int y=5,z;
        z = myfunc(y);
        System.out.println(z);
    }
}

Output:
I'm executing!
5
Kacerek answered 21/7, 2015 at 6:18 Comment(0)
C
-1

Just an addition and a lame version of others' answer

Let us consider this example below :

public class ok {

public static int foo1(int x) {
    try {
        x++;
        System.out.println("foo1 : Inside try before returning I am " + x);
        return x;
    } finally {
        x++;
        System.out.println("foo1 : Inside Finally after post Increment I am " + x);
    }
}

public static int foo2(int x) {
    try {
        x++;
        System.out.println("foo2 : I am inside another method, incremented and changed to " + x);
        return x;
    } finally {

    }
}

public static void main(String[] args) {
    ok o = new ok();
    int val = 10; // The father of all

    int z = foo1(val);
    System.out.println("After executing foo1 I am " + z);

    int x = foo2(val);
    System.out.println("After executing foo2 I am " + x);

    System.out.println("Inside main() and un-altered I am : " + val);
}
}

This is just a sample program for better understandability and synchronization of return, try, finally. Whereas, you also must consider the facts, very distinctively provided by :

  • MadProgrammer : return will supersede any other changes.
  • RishiKesh Pathak : return: returns control immediately to the caller of its method. And finally: will always be executed. but will wait for its turn

Thanks, Hope it helps.

P.S :- Parallely you must also consider accepting an answer here if you feel any of them have closely helped or completely solved your query

Classicist answered 21/7, 2015 at 8:33 Comment(6)
return doesn't 'supercede' anything.The relevant fact is that the return-expresssion is already evaluated before the finallyblock executes.Hahnert
I have just mentioned another person's comment to explain that even if there is a finally the return will execute and perform its duty first@EJP. In other words JUST WHAT YOU HAVE TOLD, may be supercede isn't the closest and perfect wordClassicist
@EJP : Have I gone wrong anywhere other than the supercede word? Please rectify me, I would be happy to do so,Classicist
Your new attempt 'the return will execute and perform its duty first' is no better. It is simply untrue. What happens first is the evaluation of the return-expression, as I have already stated. Then the finally block. Then the return. That should be quite enough 'rectification' for anybody. And we don't need to be SHOUTED AT IN CAPITALS here. People are trying to sleep.Hahnert
I was not aware of "the evaluation of the return-expression", thanks for that but as it says it stands the same that the return is executed first from the program stack while compiling. Is not it the same regardless the expression and the execution thing?Classicist
If you think my capital letters have given an impression of SHOUTING, then I apologize for that. But my sole intention was to emphasize that both are same with respect to output. As far as people are trying to sleep is concerned, i personally think that people are here to help this world rise and awake with possibilities of technology. But Sorry if that previous comment has offended you. ThanksClassicist
M
-2

Value of x has returned from myfunc() before increment in finally block.

Metastasize answered 21/7, 2015 at 6:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.