105

Why do this

} catch (SQLException sqle) {
    sqle.printStackTrace();
} finally {
    cs.close();
    rs.close();
}

Instead of this

} catch (SQLException sqle) {
    sqle.printStackTrace();
}
rs.close();
cs.close();
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
124697
  • 22,097
  • 68
  • 188
  • 315
  • Note you still have a problem in that if your first `close` throws an exception, you never get to the second. As it turns out, it's generally a good idea not to use botch `catch` and `finally` with the same `try` block. – Tom Hawtin - tackline Jan 14 '11 at 17:27
  • 1
    No more needed with java7: AutomaticResourceManagement, try(new resourceDeclartion()){} – Kanagavelu Sugumar Nov 20 '14 at 05:57

14 Answers14

114

Because if an exception gets thrown no code after the try block is executed unless the exception is caught. A finally block is always executed no matter what happens inside your try block.

JUST MY correct OPINION
  • 35,674
  • 17
  • 77
  • 99
  • 28
    >"unless the exception is caught" - The excetion is caught with catch isn't it? – 124697 Jan 14 '11 at 14:29
  • 1
    I'm talking about the overall architecture of try/catch/finally, not his specific example. – JUST MY correct OPINION Jan 14 '11 at 14:46
  • 16
    This answer is correct, a different type of exception might be thrown. – pilavdzice Jul 25 '14 at 21:38
  • 2
    pilavdzice is right, a runtime exception might be a good example – tf.alves Nov 27 '14 at 16:01
  • 2
    How is this any different? The `finally` block makes sense if there were no `catch` blocks. – azurh Nov 02 '19 at 22:13
  • Think of any resource connections for example a database connection which is no longer needed but did not get closed due to exception. The close statement could be written inside the finally block to ensure the close action. – Jude Osbert K Dec 31 '19 at 09:19
  • This simply doesn't answer the question. The correct answer is simple (and has been given in other answers below): Finally will run even when something is thrown **inside the catch block**. – rudolfbyker Jun 22 '20 at 12:23
  • I can finally see a benefit. `finally` works regardless of any error caught or not caught. Code after the `try/catch/finally` only works if the correct error was caught. If the error was missed by your catch statements, then you would raise an exception and it would crash on you. However, the `finally` statement will run regardless - what happens after an uncaught error and a finally block though? One thing I can think of also, is if your `catch` block catches all errors, then there is no difference between a finally block and just having code after the try/catch block as it will all run. – kossboss Dec 25 '20 at 02:41
  • Rule of thumb: `finally` makes sense if the code inside `catch` throws another exception, or when `try` or `catch` return something. – Robo Robok Jan 04 '23 at 17:38
30

Look at your catch block - it's going to throw DAOException. So the statements after your catch block aren't going to be executed even in the sample you've given. What you've shown (wrapping one exception in another) is one common pattern - but another possibility is that the catch block "accidentally" throws an exception, e.g. because one of the calls it makes fails.

Additionally, there may be other exceptions you don't catch - either because you've declared that the method throws them, or because they're unchecked exceptions. Do you really want to leak resources because an IllegalArgumentException got thrown somewhere?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
22

Because if an exception is thrown,

  • Code in the finally clause will execute as the exception propagates outward, even if the exception aborts the rest of the method execution;

  • Code after the try/catch block will not get executed unless the exception is caught by a catch block and not rethrown.

Bert F
  • 85,407
  • 12
  • 106
  • 123
15

According to HeadFirst Java, a finally block will run even if the try or catch block has a return statement. Flow jumps to finally and then back to return.

Aditi Garg
  • 320
  • 2
  • 9
  • 4
    I disagree. This answer is actually very important. Most answers so far were plain wrong, but Aditi gave a key reason why you might sometimes want to use "finally", so she deserves credit. – weiglt Jan 29 '18 at 22:30
10

Because it ensures that the stuff in the finally block gets executed. Stuff after catch might not get executed, say, for example, there is another exception in the catch block, which is very possible. Or you just do what you did, and throw an exception wrapping the original exception.

hvgotcodes
  • 118,147
  • 33
  • 203
  • 236
3

The finally keyword guarantees that the code is executed. In your bottom example, the close statements are NOT executed. In the top example, they are executed (what you want!)

Starkey
  • 9,673
  • 6
  • 31
  • 51
1

If you catch all errors, there should no difference, otherwise, only code inside finally block is executed because the code execution sequence is: finally code -> error throw -> code after catch hence, once your code throw any unhandled error, only finally code block works as expected.

1

Your second approach won't do the 'close' statements because it is already left the method.

nanda
  • 24,458
  • 13
  • 71
  • 90
1

This is the way to avoid resource leaks

mtraut
  • 4,720
  • 3
  • 24
  • 33
0

consider the catch can throw an exception to the higher level functions in the call stack. This will lead calling final before throwing the exception to the upper level.

Mahmoud Fayez
  • 3,398
  • 2
  • 19
  • 36
0

In http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html this is misleading (and may have originated the question):

The try block of the writeList method that you've been working with here opens a PrintWriter. The program should close that stream before exiting the writeList method. This poses a somewhat complicated problem because writeList's try block can exit in one of three ways.

1. The new FileWriter statement fails and throws an IOException.
2. The list.get(i) statement fails and throws an IndexOutOfBoundsException.
3. Everything succeeds and the try block exits normally.

The 4th way (an exception other than IOException and IndexOutOfBoundsException is thrown) is missing. The code depicted in the preceding page only catches (1) and (2) before resorting to finally.

I'm also new to Java and had the same questioning before finding this article. Latent memory tend to attach itself more to examples than to theory, in general.

Callistus
  • 11
  • 3
0

The finally block may not always run, consider the following code.

public class Tester {
    public static void main(String[] args) {
        try {
            System.out.println("The main method has run");
            System.exit(1);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("The finally block has run");
        }
    }
}

In your case, I would suggest to wrap the code inside finally block into try/catch, as this code apparently may throw an exception.

    } catch (SQLException sqle) {
        sqle.printStackTrace();
    } finally {
     try {
        cs.close();
        rs.close();
     } catch (Exception e) {
      //handle new exception here
    }
nomadus
  • 859
  • 1
  • 12
  • 28
0

The code in the finally block will get called before the exception is rethrown from the catch block. This ensures that any cleanup code that you've put in the finally block gets called. Code outside of the finally block will not be run.

Doug Mulley
  • 111
  • 5
0

this might clarify: http://www.java2s.com/Code/Java/Language-Basics/Finallyisalwaysexecuted.htm

rompetroll
  • 4,781
  • 2
  • 37
  • 50