The two code snippets are different: the second one will not close if exception handling block ends in another exception.
Here is an illustration:
public static void one() throws Exception {
try {
System.out.println("One");
throw new Exception();
} catch (Exception e) {
System.out.println("Catch one");
if (2 != 3) throw new Exception(); // "if" silences compiler's check
} finally {
System.out.println("Finally one");
}
}
public static void two() throws Exception {
try {
System.out.println("Two");
throw new Exception();
} catch (Exception e) {
System.out.println("Catch two");
if (2 != 3) throw new Exception(); // "if" silences compiler's check
}
System.out.println("After two");
}
The call to one() prints Finally one, while After two never gets printed (demo 1).
The finally block becomes even more important when you catch specific exceptions (blindly catching Exception is nearly always a bad idea), because the try block may bypass your cleanup code by throwing an exception that you do not catch. Here is another illustration:
public static void error() throws Exception {
try {
System.out.println("Try");
throw new Error();
} catch (Exception e) {
System.out.println("Catch");
throw new Exception();
} finally {
System.out.println("Finally");
}
}
This code prints Try and Finally, without Catch in the middle, because Error is not caught in the catch block (demo 2).
It goes without saying that human readers of your program will have easier time locating you clean-up code if you place it in the finally block.