9
  public class FinallyTest {
    static int i=0;
    public static void main(String a[]){
        while(true){
            try{
                i=i+1;
                return;
            }finally{
                i=i+1;
                break;
            }
        }
        System.out.println(i);
    }
}

In the above code output is '2'. What I was expecting was that nothing should be printed. What exactly does 'break' do here? Please explain. Thanks

Stan Kurilin
  • 15,614
  • 21
  • 81
  • 132
Shwetanka
  • 4,976
  • 11
  • 44
  • 68
  • It becomes clear if you debug, then you will immediately see the sequence of the steps. Try forces the jump to the finally block before returning. – Costis Aivalis Jul 02 '11 at 09:45
  • The 'break;' actually breaks the 'while'. Did you want to break the 'finally' instead? – ignis Jul 02 '11 at 09:47
  • Very nice. It's pretty cool edge case... – Jarek Potiuk Jul 02 '11 at 09:48
  • Yeah, I debugged the code but when I'm using continue statement then it should go in infinite loop. but it's not happening, instead I'm getting an error of 'try without catch or finally'. What is happening here? – Shwetanka Jul 02 '11 at 09:51
  • 1
    If you substitute break with continue the compiler should give you unreachable statement for println. If you get rid of println then you should have your infinite loop. – Costis Aivalis Jul 02 '11 at 10:05
  • this is BIG OMG question, I suggest you to learn more about java. – RustamIS Jan 20 '17 at 16:05

4 Answers4

11

The finally clause changes the "completion reason" for the try clause. For a detailed explanation, refer to JLS 14.20.2 - Execution of try-catch-finally, with reference to JLS 14.1 Normal and Abrupt Completion of Statements.

This is one of those strange edge cases in the Java language. Best practice is not to deliberately change the control flow in a finally clause because the behavior is difficult for the reader to understand.

Here's another pathological example:

// DON'T DO THIS AT HOME kids
public int tricky() {
    try {
        return 1;
    } finally {
        return 2;
    }
}
reevesy
  • 3,452
  • 1
  • 26
  • 23
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Then if I give continue instead of break then it should go in infinite loop. But this is not happening. It is giving compilation error 'try without catch or finally'. Why is this happening? – Shwetanka Jul 02 '11 at 09:47
  • @Shwetanka - are you sure about that? According to the JLS, if you replaced the `break` with `continue` you **should** get an infinite loop. OTOH, it is *possible* that you've found an obscure bug in the compiler. – Stephen C Jul 02 '11 at 09:52
  • I'm pretty sure. I'm using idea9.0 ide and when I run the code with continue it says 'try without catch or finally'. I'm not able to figure this out. – Shwetanka Jul 02 '11 at 09:57
  • 2
    @Stephen + Shwetanka : This code runs infinitely : http://www.ideone.com/XMws8 and in Eclipse too. – Saurabh Gokhale Jul 02 '11 at 10:02
  • I got the infinite loop, the problem was with the idea compiler. I used another compiler and is working fine. Thanks for help. – Shwetanka Jul 02 '11 at 10:08
  • @sgokhales - that code **should** run infinitely, according to the JLS. (The `continue` in the `finally` clause changes the completion reason ... to continue the next loop iteration.) – Stephen C Nov 28 '11 at 22:05
5

Code in the finally clause is bound to execute.

Here's the flow :

So, after incrementing the value of i to 1 in try block, it encounters the return statement. But, it has finally block too. So it executes finally block and their again, it increments the value of i to 2. Then the break in encountered and the loop is exited.

So, the value of i = 2 at the end. Hope the flow is clear.

Saurabh Gokhale
  • 53,625
  • 36
  • 139
  • 164
  • Then if I give continue instead of break then it should go in infinite loop. But this is not happening. It is giving compilation error 'try without catch or finally'. Why is this happening? – Shwetanka Jul 02 '11 at 09:49
  • Nope, it does give a different error `unreachable statement : System.out.println(i);` : http://www.ideone.com/nX3G8 ... – Saurabh Gokhale Jul 02 '11 at 09:51
  • Comment that println statement then see, the way break is working continue should make this code run in infinite loop logically, but this is not happening. – Shwetanka Jul 02 '11 at 09:53
  • 1
    Yes, it does run in an infinite loop. But there's nothing to print. Try debugging the code and you yourself will get the ***point***. Just add `System.out.println(i);` after the statement `i=i+1` in the finally block. The code runs infinitely. – Saurabh Gokhale Jul 02 '11 at 09:59
  • ... or place a System.out.println() inside the loop. – ignis Jul 02 '11 at 10:00
4

It breaks the loop and 'overrides' the return.

  1. finally blocks are always executed
  2. what happens in the finally can override what has happened before - thrown exceptions, return statements.
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
0
public static void main(String a[])
{
    while(true) <<< #1
    {
        try
        {
            i=i+1;  <<< #2
            return;
        }
        finally
        {
            i=i+1;  <<< #3
            break;  <<< #4
        }
    }
    System.out.println(i);  <<< #5
}

This is what BlueJ Tracing shows.

Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417