46

The "finally" block is always executed when the try-catch ends, either in case of exception or not. But also every line of code outside and after the try-catch is always executed. So, why should I use the finally statement?

Example:

try {
    //code...
} catch (Exception e) {
    //code...
} finally {
    System.out.println("This line is always printed");
}
System.out.println("Also this line is always printed !! So why to use 'finally'?? ");
Aarath
  • 481
  • 1
  • 4
  • 4
  • 1
    With catch (Throwable t) instead of catch (Exception e) the last line would always be executed. – Aarath Apr 03 '13 at 01:06
  • 2
    It is a frequent pattern to throw new exceptions in catch blocks, and finally lets you clean up stuff from the try block before sending out the new exception. It is very handy. The notation also makes code more semantic. – le3th4x0rbot May 03 '13 at 23:49

6 Answers6

24

The most useful case is when you need to release some resources :

InputStream is = ...
try {
    //code...
} catch (Exception e) {
    //code...
} finally {
    is.close();
}

More generally, you use it when you want to be sure your code is executed at the end, even if there was an exception during execution :

long startTime = System.currentTimeMillis();
try {
    //code...
} catch (Exception e) {
    //code...
} finally {
    long endTime = System.currentTimeMillis();
    System.out.println("Operation took " + (endTime-startTime) + " ms");
}

The idea of this finally block always being executed is that it's not the case for the first line following the whole block

  • if the catch block lets some throwable pass
  • if it rethrows itself an exception, which is very frequent
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
7

But also every line of code outside and after the try-catch is always executed.

Well, not always. For instance we can throw Error which is not subtype of Exceptuon, but Throwable so it will NOT be caught by catch(Exception e) {..}. In such case before try block will move control flow out of method corresponding finally section will be invoked, but code after it will not.

Take a look at this code

public static void main(String[] args) {
    try{
        //...
        throw new Error("something went terribly wrong");
    } catch (Exception e) {//will NOT catch Error
        e.printStackTrace();
    } finally{//this will be invoked regardless of what happens in try,              
        System.out.println("finally block");
    }

    //if Error will be thrown in above `try` it will move flow of control 
    //from this method, which will prevent it from reaching 
    //this place and executing code after this comment
    System.out.println("after finally... may not be executed");
}
Pshemo
  • 122,468
  • 25
  • 185
  • 269
  • The example code in Aarath's question would catch the RuntimeException. The code after the finally block would in that case also run. – jarnbjo Apr 02 '13 at 16:05
  • @jarnbjo Then instead of `RuntimeException` program can throw `Error` which is also unchecked. Now you will probably say that it can be handled by catching `Throwable` but is that really how real programs work? If we start catching all errors then we really wont need `finally` section because we can move it at the end of every catch block and after try-catch section in case no catch was executed. – Pshemo Apr 02 '13 at 16:21
  • Your problem is that you're trying to explain a generic behaviour using a very narrow explanation, which only covers a very specific cause. There are several situations where code execution will not continue past the finally block, e.g. if any exception is thrown in the try block and not caught with a matching catch block (it is completely irrelevant if it is a runtime or unchecked exception), if a new exception is thrown in a catch block or if code execution is interrupted with any other statement, e.g. a return statement in the try block. – jarnbjo Apr 02 '13 at 16:28
  • @jarnbjo OP asked why he should use `finally` block believing that everything after try-catch will be always executed. To show him that it is not always true one simple example should be enough, don't you think? – Pshemo Apr 02 '13 at 16:44
  • No, it would be much better to explain why his statement is wrong. – jarnbjo Apr 02 '13 at 16:51
  • @jarnbjo OK, it is hard to disagree that full explanation is better than one example (that is why +1 for you), but I will leave this answer as one of counter-examples of OP assumption. Hope you don't mind. – Pshemo Apr 02 '13 at 17:00
7

The last System.out.println (after the finally block) will only be run if the exception thrown in the try block is actuaclly caught with a catch block and if the execution is not interrupted by e.g. a return statement.

In your example, the finally block will always be run, but the execution will only continue past the finally block if no Error is thrown in the try block (it would not be caught), if no Throwable is thrown in the catch block and there is no other statement, which will interrupt execution.

jarnbjo
  • 33,923
  • 7
  • 70
  • 94
1

The finally block is a key tool for preventing resource leaks. When closing a file or otherwise recovering resources, place the code in a finally block to ensure that resource is always recovered.

But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

More here

tmwanik
  • 1,643
  • 14
  • 20
-1

suppose you are writing in the file and suddenly it creates an exception the how you close the file .then finally help you and also for database transaction finally block helps a lot

Biswajit
  • 2,434
  • 2
  • 28
  • 35
-2

finally block's only purpose is to close the resources which you have opened inside try block. resources could be anything like database connections,File writing/reading etc:

Connection conn= null;
try {
 conn= get the db conn;
//do some DML/DDL
}
catch(SQLException ex) {

}
finally {
conn.close();
}
PermGenError
  • 45,977
  • 8
  • 87
  • 106