0

I've seen this behavior explained away because it was usually an immutable String in the finally block but I don't understand why an int primitive would behave this way.

"i" is not passed by value as an argument in a method. The method is directly setting the i class variable. This is a obvious because the value of i is changed when printed after the method finishes.

It is also clear that it has been changed prior to the return statement in the try block since the print in the finally block prints first.

public class Test {
    static int i = 0;
    public static void main(String[] args) {

        System.out.println("Try Block returns: " + methodReturningValue());
        System.out.println("Value of i after method execution is " + i);
    }


    static int methodReturningValue()
        {


            try
            {
                i = 1;
                System.out.println("try block is about to return with an i value of: "+  i);
                return i;
            }
            catch (Exception e)
            {
                i = 2;
                return i;
            }
            finally
            {
                i = 3;
                System.out.println("Finally block: i has been changed to 3");
            }
        }


    }

Output:

try block is about to return with an i value of: 1
Finally block: i has been changed to 3
Try Block returns: 1
Value of i after method execution is 3
A. J. Green
  • 93
  • 2
  • 8
  • 1
    https://stackoverflow.com/questions/65035/does-a-finally-block-always-get-executed-in-java might help – seenukarthi Dec 23 '19 at 06:45
  • 1
    _"I've seen this behavior explained away because it was usually an immutable String"_ where have you seen this explanation? That explanation makes no sense at all. Assigning a different value to a field or variable in the finally will simply not affect the returned value using `return`. Java is pass by value, not pass by reference. – Mark Rotteveel Dec 23 '19 at 06:47
  • Mark Rotteveel, Nothing is passed here because there are no arguments in the method. That's why the i variable is actually changed. As you can see by the final print statement. – A. J. Green Dec 23 '19 at 06:50
  • 1
    Some thing is passed: the return value is passed out of the method to the caller. However, I think you're confusing reassigning a new value in a variable with changing the contents of an object that is referenced by a variable. – Mark Rotteveel Dec 23 '19 at 06:51
  • 1
    Read last line: https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.17 – Sumit Singh Dec 23 '19 at 06:53
  • Mark Rotteveel, I understand that the return statement is passing a value but the value comes from class variable i that has been set to a value of 3 in the finally block prior to try block return. – A. J. Green Dec 23 '19 at 07:05
  • Thank you Karthikeyan Vaithilingam,. I think I found the answer to this behavior in one of the answers in your link: "Here's an elaboration of Kevin's answer. It's important to know that the expression to be returned is evaluated before finally, even if it is returned after." It is not an issue of value but order of execution and return. – A. J. Green Dec 23 '19 at 07:28
  • 1
    That is correct. Evaluation order, not immutability etc. – user207421 Dec 23 '19 at 08:46

1 Answers1

-1

Yes, finally block always run after 'return' and 'throw' an exception, your code same as:

public class Test {
    static int i = 0;
    public static void main(String[] args) {

        System.out.println(methodReturningValue());
        System.out.println(i);
    }


    static int methodReturningValue()
    {

        int answer = 0;
        try
        {
            i = 1;
            answer = i;
        }
        catch (Exception e)
        {
            i = 2;
            answer = i;
        }
        i = 3;
        System.out.println("i=3");
        return answer;
    }


}
dung ta van
  • 988
  • 8
  • 13
  • dung ta van, Isn't it running right before "return"? Isn't that what the print statements are indicating? – A. J. Green Dec 23 '19 at 07:02
  • dung ta van, check the output. The finally block executes before the try return. : i has been changed to value of 3 prior to try block return Try Block returns: 1 Value of i after method execution is: 3 – A. J. Green Dec 23 '19 at 07:09
  • I don't know exactly you mean, if ```finally``` present, the function will create a temporary variable (answer). It prints(i=3) first and return 'answer' right after, because 'answer' has type is int (value type) so it's value has not changed, if you use AtomicInteger you will get answer 'i=3, 3, 3` – dung ta van Dec 23 '19 at 07:27
  • public class Test { static AtomicInteger i = new AtomicInteger(); public static void main(String[] args) { System.out.println(methodReturningValue()); System.out.println(i); } static AtomicInteger methodReturningValue() { try { i.set(1); return i; } catch (Exception e) { i.set(2); return i; } finally { i.set(3); System.out.println("i=3"); } } } – dung ta van Dec 23 '19 at 07:29
  • The question is why the OP's code *doesn't* work the same as this code. Which it most certainly does not. – user207421 Dec 23 '19 at 08:45