28

哈哈,咱们团队早就不用try-catch-finally关闭资源了!

 3 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzAxMTg2MjA2OA%3D%3D&%3Bmid=2649855304&%3Bidx=2&%3Bsn=3405a28e08dcf9c3b5d6192b6b695dfa
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

640?wx_fmt=gif

代码一定得写的优雅一点!

你还在使用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的定义:

所有实现了 java.lang.AutoCloseable [1] 接口(其中,它包括实现了  java.io.Closeable [2] 的所有对象),可以使用作为资源。简单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();
}
}
}

打印结果:

hello
Resource 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();
}
}
}

打印结果:

hello
Resource say hello
Resource2 is closed
Resource is closed

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

那么它的底层原理又是怎样的呢,由皮皮甜独家揭秘优雅关闭资源背后的密码秘密

查看编译的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【屏蔽】的异常

怎么样,是不是很简单呢,如果学会了话来个在看吧!

640?wx_fmt=png

参考资料

[1]

java.lang.AutoCloseable: http://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html

[2]

java.io.Closeable: http://docs.oracle.com/javase/8/docs/api/java/io/Closeable.html

作者:何甜甜在吗

来源:https://urlify.cn/y67ZRb

----------  END  ----------

重磅!后厂技术官-技术交流群已成立

扫码可添加后厂技术官助手, 可申请加入后厂技术官大群和细分方向群,细分方向已涵盖: Java、Python、机器学习、大数据、人工智能 等群。

一定要备注: 开发方向+地点+学校/公司+昵称 (如Java开发+北京+快手+阿信) ,根据格式备注,可更快被通过且邀请进群

▲长按加群

推荐阅读

•  Fastjson在阿里内网被喷成一坨屎了? 作者回应..

•  NOI金牌得主、姚班毕业生张昆玮放弃谷歌高薪回乡教二本,网友:很羡慕他

•  今生不再见, VS Code !

•  任正非:华为没有 996,更没有 007!

•  苹果为什么不封杀 Flutter 呢?

推荐一个技术号

Github实验室, 由国内一线大厂专家、985博士、硕士组成的团体运营。 主要分享和研究业界实用、有趣的开源项目,学习资源,开发工具,学术交流。

关注就无套路送你一份5000页Java面试最强合集PDF。

最近面试BAT,整理一份面试资料 大厂Java面试通关指北 ,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点“ 在看 ”,关注公众号并回复  BAT  领取,更多内容陆续奉上。

如有收获,点个在看,诚挚感谢 明天见(。・ω・。)ノ♡


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK