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.
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.
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?
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.
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.
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.
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.
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.