views:

154

answers:

7

I think on the following examples; but could not figure out what the importance of the finally block is. Can you tell me the difference of the executions of these two code samples? Also a real life example can be helpful.

Sample 1:

    try{
       // some code 1
    }catch(Exception ex){
       // print exception   
    }finally{
       // some code 2            
    }

Sample 2:

    try{
      // some code 1
    }catch(Exception ex){
      // print exception   
    }
    // some code 2
+2  A: 

You use the finally block in order to cleanup and run any code that should run whether an exception was thrown (and caught) or not. This includes code that you have in the catch block.

Oded
Do you mean, if I have catch block code which can throw an exception? In the case where I just call the print function, finally has no importance??
abuzittin
+5  A: 

The finally block is executed even if e.g. an Error is thrown, which is not caught by the catch block in your example. So you can put cleanup code in the finally block, which should be run always, regardless of the outcome of the operations in the try and catch blocks.

Note that usually catch blocks catch more specific types of exceptions - often only checked exceptions -, so in most cases the difference between the two code examples above is very definite.

Update: you may say that your catch block can never throw an exception, so finally is not needed. However, note two things:

  • this is only the current state of the code, and it can change in the future - can you guarantee that the future programmer who adds some potentially exception-throwing code in the catch block, will remember to put the cleanup code after it into a finally block?
  • try-catch-finally is a programming idiom which makes it easier for people reading the code to understand what's going on. If you don't use the common idiom, you risk misunderstanding, thus bugs on the long term.
Péter Török
Exception or Error. If we re-think my question with Error instead of Exception, what will your answer be?
abuzittin
Thank for your update part.
abuzittin
@abuzittin, I have updated my post in the meantime, which I believe answers your question. Btw it should be `Throwable`, not `Error`.
Péter Török
+1 for idiom. There's no point in avoiding `finally` but trying to replicate its semantics when `finally` is more idiomatic anyway.
polygenelubricants
+11  A: 

There is a big difference in the two snippets you've presented, e.g. when the catch block itself throws an exception, the finally block would still be executed by its semantics.

That is the following snippet prints "Finally!", but not "What about me???":

    try {
        throw null;     // throws NullPointerException!
    } catch (Exception e) {
        int oops = 1/0; // throws ArithmeticException!
    } finally {
        System.out.println("Finally!"); // still gets executed!
    }
    System.out.println("What about me???"); // doesn't get executed!

Generally speaking, the finally of a try block practically always gets executed. There's no such guarantee for any code following the try block.


But what if my catch block is just a simple print statement?

There's still no guarantee that it won't throw something. Something could still go wrong in e.g. the construction for the exception detailed message.

Even if you make a best effort guarantee that the catch code is "safe" and the code following the try statement will always be executed, the question then becomes "Why?". Why avoid finally but then try so hard to replicate its semantics?

finally semantics is guaranteed, requiring no burden of proof from either the writer or the reader of the code. Precisely because of this, it's idiomatic to use finally block to put mandatory "clean-up" code. Using finally guarantees correctness and enhance both writability and readability.

polygenelubricants
Got the idea. In the case where I just call the print function in catch block, finally has no importance??
abuzittin
@abuzittin: more than the semantics, the PATTERN itself is important. It's idiomatic to put mandatory cleanup codes in `finally`. The `finally` semantics makes the intent much clearer. Also, a simple print can, in some circumstances, throw an exception (e.g. `IOException`, logger went bonkers, message construction went awry, etc).
polygenelubricants
Mind you, it could still fail to execute if something catastrophic happens (eg: user kills the process or unplugs the machine), but as far as exceptions go you're fine.
David X
+1  A: 

it is helpful when we want to free up the resources we used in try block. So the only place to execute them without missing at any case is finally block. Since if exception is thrown, java does not execute code which immediate after that. it directly jump to the catch block.

RN
A: 

Note that you can have even try-finally without a catch:

try{
   // some code 
}finally{
   // cleanup code
}

An example therefore could be a method that wants to propagate exceptions to the caller, but still needs clean up code, like releasing a look.

PartlyCloudy
A: 

In case where the statements in try block throw unchecked exceptions, finally block will get executed allowing programmer to take relevant actions.

Tushar Tarkas
A: 

In real life, the finally block is used to close opened resources even if an exception occurs. For example, when you read (or write) a file, when you access to a database, etc.

public void readFile(String fileName) {
    FileReader fr;
    BufferedFileReader bfr;

    try {
        fr = new FileReader(fileName);
        bfr = new BufferedFileReader(fr);
        // ...
    } catch (IOException ioe) {
        // ...
    } finally {
        // TO ENSURE THAT THE READERS ARE CLOSED IN ALL CASES
        if (bfr != null) { 
            try {
                bfr.close();
            } catch (IOException ignoredIOE) {}
        }
        if (fr != null) { 
            try {
                fr.close();
            } catch (IOException ignoredIOE) {}
        }
    }
}
Benoit Courtine