Java – Difference Between Code in Finally Clause and After Catch Clause

exceptionsjava

My java code is just like below:

public void check()throws  MissingParamException{
    ......
}
public static void main(){
    PrintWriter out = response.getWriter();
    try {
        check();
    } catch (MissingParamException e) {
        // TODO Auto-generated catch block
        out.println("message:"+e.getMessage());
        e.printStackTrace();
        out.close();
    }finally{
        out.close();
    }
    //out.close();
}

Then, my confusion is: what the difference if I put out.close() in a finally code block or if I just remove finally code block and put out.close() behind catch clause (which has been commented in the code). I know that in both ways, the out.close() will be executed because I know that whether the exception happened, the code behind the catch clause will always be executed.

Best Answer

The finally {} block is always called (unless you call exit() before finally is reached - but you won't be doing that most of the time).

The purpose of finally is to clean up any resources allocated in the try {} block, even if something was thrown and it hit the catch{} block.

Consider the code:

public class Hello {

    public static void main(String[] args) {
        hello();
    }

    public static void hello() {
        try {
            System.out.println("hi");
            return;
        } catch (RuntimeException e) {
        } finally {
            System.out.println("finally");
        }
    }
}

While there isn't any resource allocation in this, just pretend there is. This will print out:

hi
finally

If you had opened a file in the try block, the finally is the place to clean it up. If you had opened one file, and then tried to open another one (that threw an exception), the finally is the place to clean that up.

If there was an uncaught exception by the catch block, then the finally would run, and the exception would get passed on up.

Putting out.close() in the catch and the finally is redundant - because it will be run in the finally block - on a caught exception or successful completion of the try.

With the existing code, the following code paths are possible:

  • No exception:

    1. check() - no exception thrown
    2. finally { } - out.close
  • Caught exception:

    1. check() - MissingParamException thrown
    2. catch { } - stuff and out.close
    3. finally { } - out.close
  • Uncaught exception:

    1. check() - NPE thrown
    2. finally { } - out.close

You should be able to see from this, the finally is always called, and in the caught exception, out.close() is invoked twice.

The associated spec is ยง14.20.2 in Java SE 7 language specification.

Related Topic