Please, consider the following code:
class Bum implements AutoCloseable{
public void bu() throws Exception{
System.out.println("Bu");
throw new Exception();
}
@Override
public void close(){
System.out.println("Closed");
}
}
public class TestTryWith {
private static void tryWith(){
try (Bum bum=new Bum()){
bum.bu();
}catch (Exception ex){
System.out.println("Exception");
//ex.printStackTrace();
}
}
private static void tryCatchFinally(){
Bum bum=new Bum();
try{
bum.bu();
}catch (Exception ex){
System.out.println("Exception");
}finally{
bum.close();
}
}
public static void main(String[] args) {
tryCatchFinally();
System.out.println("------------");
tryWith();
}
}
And the output is:
Bu
Exception
Closed
------------
Bu
Closed
Exception
I've read that try-with-resources is converted to try-catch-finally block by the compiler. However, as you see the order is different. When we use try-with-resources the close method is invoked BEFORE the catch clause. Why?
As ever, the answer is in the JLS - in this case, section 14.20.3.2. Basically, if you have catch or finally blocks in your try-with-resources statement, that's converted into a "normal" try/catch/finally block which contains a try-with-resources statement without your specified catch/finally block - but with the one that calls close automatically. So your try-with-resources snippet is effectively:
try {
try (Bum bum = new Bum()) {
bum.bu();
}
} catch (Exception ex){
System.out.println("Exception");
//ex.printStackTrace();
}
Which is in turn roughly equivalent to:
try {
Bum bum = new Bum();
try {
bum.bu();
} finally {
// It's more complicated than this...
bum.close();
}
} catch (Exception ex){
System.out.println("Exception");
//ex.printStackTrace();
}
So the "inner" finally
block which closes the resource is executed before the catch
block in the "outer" try
statement.
See more on this question at Stackoverflow