请考虑以下代码:
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();
}
}
输出是:
Bu
Exception
Closed
------------
Bu
Closed
Exception
我已经读过,try-with-resources被编译器转换为try-catch-finally块。但是,正如您所看到的顺序不同。当我们使用try-with-resources时,在catch子句之前调用close方法。为什么呢?
答案 0 :(得分:4)
与往常一样,答案在JLS中 - 在这种情况下,section 14.20.3.2。基本上,如果你在try-with-resources语句中有catch或finally块,那么它将被转换为一个“普通”try / catch / finally块,其中包含一个try-with-resources语句,而不是你指定的catch / finally阻止 - 但是自动调用close的那个。因此,您的try-with-resources代码段实际上是:
try {
try (Bum bum = new Bum()) {
bum.bu();
}
} catch (Exception ex){
System.out.println("Exception");
//ex.printStackTrace();
}
这又大致相当于:
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();
}
因此,关闭资源的“内部”finally
块在“外部”catch
语句中的try
块之前执行。