博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用try-with-resources优雅关闭资源
阅读量:6244 次
发布时间:2019-06-22

本文共 5478 字,大约阅读时间需要 18 分钟。

代码一定得写的优雅一点

你还在使用try-catch-finally关闭资源吗,如果是,那么就有点out了。皮皮甜手把手教你使用JDK7引用的try-with-resource

JDK7之前资源的关闭姿势:

/** * jdk7以前关闭流的方式 * * @author hetiantian * */public class CloseResourceBefore7 {    private static final String FileName = "file.txt";    public static void main(String[] args) throws IOException {        FileInputStream inputStream = null;        try {            inputStream = new FileInputStream(FileName);            char c1 = (char) inputStream.read();            System.out.println("c1=" + c1);        } catch (IOException e) {            e.printStackTrace();        } finally {            if (inputStream != null) {                inputStream.close();            }        }    }}复制代码

JDK7及以后关闭资源的正确姿势:try-with-resource Resource的定义:所有实现了  接口(其中,它包括实现了  的所有对象),可以使用作为资源。 简单Demo进行证实: 实现java.lang.AutoCloseable接口的Resource类:

/** * 资源类 *  * @author hetiantian * */public class Resource implements AutoCloseable {    public void sayHello() {        System.out.println("hello");    }    @Override    public void close() throws Exception {        System.out.println("Resource is closed");    }}复制代码

测试类CloseResourceIn7.java

/** * jdk7及以后关闭流的方式 * * @author hetiantian * */public class CloseResourceIn7 {    public static void main(String[] args) {        try(Resource resource = new Resource()) {            resource.sayHello();        } catch (Exception e) {            e.printStackTrace();        }    }}复制代码

打印结果:

helloResource is closed复制代码

当存在多个打开资源的时候: 资源二Resource2.java

/** * 资源2 *  * @author hetiantian * */public class Resource2 implements AutoCloseable {    public void sayhello() {        System.out.println("Resource say hello");    }    @Override    public void close() throws Exception {        System.out.println("Resource2 is closed");    }}复制代码

测试类CloseResourceIn7.java

/** * jdk7及以后关闭流的方式 * * @author hetiantian * */public class CloseResourceIn7 {    public static void main(String[] args) {        try(Resource resource = new Resource(); Resource2 resource2 = new Resource2()) {            resource.sayHello();            resource2.sayhello();        } catch (Exception e) {            e.printStackTrace();        }    }}复制代码

打印结果:

helloResource say helloResource2 is closedResource is closed复制代码

即使资源很多,代码也可以写的很简洁,如果用jdk7之前的方式去关闭资源,那么资源越多,用fianl关闭资源时嵌套也就越多

那么它的底层原理又是怎样的呢,由皮皮甜独家揭秘优雅关闭资源背后的密码 查看编译的class文件CloseResourceIn7.class:

public class CloseResourceIn7 {    public CloseResourceIn7() {    }    public static void main(String[] args) {        try {            Resource resource = new Resource();            Throwable var2 = null;            try {                resource.sayHello();            } catch (Throwable var12) {                var2 = var12;                throw var12;            } finally {                if (resource != null) {                    if (var2 != null) {                        try {                            resource.close();                        } catch (Throwable var11) {                            var2.addSuppressed(var11);                        }                    } else {                        resource.close();                    }                }            }        } catch (Exception var14) {            var14.printStackTrace();        }    }}复制代码

可以发现编译以后生成了try-catch-finally语句块 finally中的var2.addSuppressed(var11);是不是有疑问?️ 其实这么做是为了处理异常屏蔽的 我们将代码修改一下 资源Resource.java

/** * 资源类 * * @author hetiantian * */public class Resource implements AutoCloseable {    public void sayHello() throws Exception {        throw new Exception("Resource throw Exception");    }    @Override    public void close() throws Exception {        throw new Exception("Close method throw Exception");    }}复制代码

两个方法里面都抛出异常

测试类CloseResourceIn7.java

/** * jdk7及以后关闭流的方式 * * @author hetiantian * */public class CloseResourceIn7 {    public static void main(String[] args) {        try {            errorTest();        } catch (Exception e) {            e.printStackTrace();        }    }    private static void errorTest() throws Exception {        Resource resource = null;        try {            resource = new Resource();            resource.sayHello();        }        finally {            if (resource != null) {                resource.close();            }        }    }}复制代码

打印结果:

java.lang.Exception: Close method throw Exception	at com.shuwen.Resource.close(Resource.java:15)	at com.shuwen.CloseResourceIn7.errorTest(CloseResourceIn7.java:27)	at com.shuwen.CloseResourceIn7.main(CloseResourceIn7.java:12)复制代码

只打印了最后出现的异常【异常屏蔽】这样会给开发人员排查错误带来一定的困难 我们换成try-with-resource方法实现CloseResourceIn7.java

/** * jdk7及以后关闭流的方式 * * @author hetiantian * */public class CloseResourceIn7 {    public static void main(String[] args) {        try {            errorTest();        } catch (Exception e) {            e.printStackTrace();        }    }    private static void errorTest() throws Exception {        try(Resource resource = new Resource()) {            resource.sayHello();        }    }}复制代码

打印信息:

java.lang.Exception: Resource throw Exception	at com.shuwen.Resource.sayHello(Resource.java:10)	at com.shuwen.CloseResourceIn7.errorTest(CloseResourceIn7.java:20)	at com.shuwen.CloseResourceIn7.main(CloseResourceIn7.java:12)	Suppressed: java.lang.Exception: Close method throw Exception		at com.shuwen.Resource.close(Resource.java:15)		at com.shuwen.CloseResourceIn7.errorTest(CloseResourceIn7.java:21)		... 1 more复制代码

可以发现,异常信息中多了一个Suppressed的提示,告诉我们这个异常其实由两个异常组成,Close method throw Exception这个异常是被Suppressed【屏蔽】的异常

总结 怎么样,是不是很简单呢,如果学会了话

转载地址:http://zvpia.baihongyu.com/

你可能感兴趣的文章
Oracle11g x64使用Oracle SQL Developer报错:Unable to...
查看>>
概率论与数理统计14--方差
查看>>
关于PHP中按位取反问题
查看>>
scrapy爬取某网站,模拟登陆过程中遇到的那些坑
查看>>
设计师的知识管理
查看>>
Struts中ActionForm的作用
查看>>
昨天开始学习安卓
查看>>
centos 7 chrome安装
查看>>
为什么单个TCP连接很难占满带宽
查看>>
最佳开发实践:自动化单元测试(PHP)
查看>>
postgresql 9.3 install centos6.x
查看>>
Groovy中方法的调用实现方式浅析(CallSite)
查看>>
JBoss 系列六十三:JBoss 7/WildFly 集群之 Java Persistence API (JPA) - II(Hibernate查询缓存和二级缓存示例)...
查看>>
lua入门交流 模拟 C++ 类 的实现 或 使用
查看>>
设置MySql数据库的字符编码为UTF8
查看>>
设计模式proxy
查看>>
Java 通过JDBC连接管理数据库
查看>>
All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com
查看>>
LigerUI Grid(表格)分页要注意的地方
查看>>
邻居子系统
查看>>