Java:try-with-resources vs try-catch-finally关于autoclosing的顺序

时间:2015-09-29 16:21:18

标签: java

请考虑以下代码:

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方法。为什么呢?

1 个答案:

答案 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块之前执行。