欢迎来到刘志红的博客

别人说程序员是“搬砖”的码农,但我们知道自己是追求个性的艺术家。也许我们不会过多的在意自己的外表和穿着,但在不羁的外表下,骨子里追求着代码的美、系统的美、设计的美。
扩大
缩小

effective解读-第九条 try-with-resource代替try-fanilly释放资源

做java的都知道,有写资源使用完毕后要及时的释放否则会导致OOM,例如流资源,我们一般放在finally中进行释放(确保流资源一定被释放)

try-finally的缺点有两个,使用try-with-resources完美解决

1. AutoCloseable接口的close本身就会抛出异常,所以如果同时关闭多个异常的话就会使代码显得非常臃肿

 

//例如POIUtils工具类中的代码
try {
    out = response.getOutputStream();
    workbook = new XSSFWorkbook(byteArrayInputStream);
    workbook.write(out);
    out.flush();
} catch (IOException e) {
    e.printStackTrace();
    throw new AppException();
} finally {
    try {
        byteArrayInputStream.close();
    } catch (IOException e) {
        log.error("关闭流异常", e);
    }
    try {
        if (out != null) {
            out.close();
        }
    } catch (IOException e) {
        log.error("关闭流异常", e);
    }
    try {
        if (workbook != null) {
            workbook.close();
        }
    } catch (IOException e) {
        log.error("关闭流异常", e);
    }
}
//改进后的版本
try (
    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
    OutputStream out = response.getOutputStream();
    Workbook workbook = new XSSFWorkbook(byteArrayInputStream);
) {
    workbook.write(out);
    out.flush();
} catch (IOException e) {
    e.printStackTrace();
    throw new AppException();
}

 

2. try中和finally中都有异常堆栈只会保留后面的异常,导致起那面的异常难以排查

public class Demo2 {
    private static class TestDemo implements AutoCloseable{
        @Override
        public void close(){
            throw new RuntimeException();
        }
    }

    public static void main(String[] args) {
        TestDemo testDemo = null;
        try{
            testDemo = new TestDemo();
            //异常
            int i = 1 / 0;
        }finally {
            testDemo.close();
        }
    }
}
//运行结果,只能看到finally里面的异常,而忽略了业务中的异常
Exception in thread "main" java.lang.RuntimeException
    at infosecuritydemo.demo.optional.Demo2$TestDemo.close(Demo2.java:11)
    at infosecuritydemo.demo.optional.Demo2.main(Demo2.java:21)
//改进后的版本
public static void main(String[] args) {
    try (TestDemo testDemo = new TestDemo()) {
        int i = 1 / 0;
    }
}
//运行后异常明显的打印出来
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at infosecuritydemo.demo.optional.Demo2.main(Demo2.java:20)
      //会自动调用Throwable的getSuppressed()方法为我们打印出被隐藏的异常
    Suppressed: java.lang.RuntimeException
        at infosecuritydemo.demo.optional.Demo2$TestDemo.close(Demo2.java:14)
        at infosecuritydemo.demo.optional.Demo2.main(Demo2.java:21)

 

posted on 2021-03-29 10:23  MR_程序猿刘  阅读(255)  评论(0编辑  收藏  举报

导航