Comment by xxs

6 days ago

finally stuff is executed prior to the 'return'; effectively it's placed before the 'return' statement. So it's quite obvious.

No, it's not executed before the return, it's executed in the middle of it, so to speak:

    class Main {
        static int f() { System.out.println("f()"); return 1; }
        static int g() { System.out.println("g()"); return 2; }

        static int h() {
            try {
                return f();
            } finally {
                return g();
            }
        }

        public static void main(String[] args) {
            System.out.println(h());
        }
    }

will print

    f()
    g()
    2

If "finally" block was executed before the "return" in the "try", the call to f() would not have been made.

  • Yes, very much is... return is not a single statement or a single opcode. the call to f() is returned on the stack, that's assigned to some local variable via istore, there is no 'ireturn', yet. Then the g() method is called along with whatever is printed, and the next instruction can be ireturn. which would return '2' indeed.

    • > return is not a single statement.

      It is a single statement. It's just that executing it contains of two parts: evaluating the expression, and the non-local transfer of control ― and the weird part is that this control transfer can be hijacked. And it is weird, you can't do this with e.g. "if": if the test condition is evaluated successfully, then the control will go into one of the branches, and you can't mess with that... but with "return", you can abort this transfer of control. Which is, again, weird: all other expression-evaluating statements can go haywire only if the evaluation of the expression inside them throws an exception — but if that doesn't happen, the control transfer is completely trivial, with no special rules about try-catch blocks.

      3 replies →