try-with-resources语句

发布时间 2023-10-04 16:54:52作者: 沈自在。

try-with-resources语句

try-with-resources语句是一种声明了一种或多种资源的try语句。资源是指在程序用完了之后必须要关闭的对象。try-with-resources语句保证了每个声明了的资源在语句结束的时候都会被关闭。任何实现了java.lang.AutoCloseable接口的对象,和实现了java.io.Closeable接口的对象,都可以当做资源使用。

因为 Closeable 接口继承了 AutoCloseable

如:

public interface Closeable extends AutoCloseable {
    public void close() throws IOException;
}

其实这种方法只是简化了代码的冗杂程度,反编译的结果一定还是 判断非空加 finally

写法初识

此时如果将 资源写入到表达式中,那么无论表达式是正常结束还是异常技术,其都会被关闭,即使抛出了异常。

@Slf4j
class Test implements AutoCloseable{

    public void testData(){
        log.debug("测试样例");
    }

    @Override
    public void close() throws Exception {
        log.debug("程序正在关闭异常");
    }
}

public class TestTryWithResource {
    public static void main(String[] args) {
        try(Test test = new Test()){
            test.testData();
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}

运行结果

10:50:31.961 [main] DEBUG nio.testselector.Test - 测试样例
10:50:31.963 [main] DEBUG nio.testselector.Test - 程序正在关闭异常

同时反编译刚才的 class 会发现只是编译器给我们生成了非空判断以及finally

异常屏蔽

那么如果在 close 方法 和 testData 方法中继续抛出异常会发生什么呢?

@Slf4j
class Test implements AutoCloseable{

    public void testData() throws Exception{
        throw new Exception("testData 出现异常");
    }

    @Override
    public void close() throws Exception {
        throw  new MyException("我自定义的异常");
    }
}

结果如下

java.lang.Exception: testData 出现异常
	at nio.testselector.Test.testData(TestTryWithResource.java:10)
	at nio.testselector.TestTryWithResource.main(TestTryWithResource.java:22)
	Suppressed: nio.testselector.MyException: 我自定义的异常
		at nio.testselector.Test.close(TestTryWithResource.java:15)
		at nio.testselector.TestTryWithResource.main(TestTryWithResource.java:21)

这说明了一个什么问题呢?异常信息中的 Suppressed 又是什么意思呢???

顾名思义, Suppressed exceptions是在代码中引发的异常,但是以某种方式被忽略了。 如果您还记得try-catch-finally块的执行顺序以及它们如何返回任何值或异常,那么您会记得, 如果try块中也引发了异常,则可以抑制在finally块中引发的异常

也就是说这种写法告诉了我们,异常其实是由俩个异常组成的,而MyException是被Suppressed的异常。