接下来,我们在自定义类中再添加一个 out() 方法,
class MyResourceOut implements AutoCloseable { @Override public void close() throws Exception { System.out.println("关闭自定义资源"); } public void out() throws Exception{ System.out.println("沉默王二,一枚有趣的程序员"); } }
这次,我们在 try 中调用一下 out() 方法:
public class TrywithresourcesCustomOut { public static void main(String[] args) { try (MyResourceOut resource = new MyResourceOut();) { resource.out(); } catch (Exception e) { e.printStackTrace(); } } }
再来看一下反编译的字节码:
public class TrywithresourcesCustomOut { public TrywithresourcesCustomOut() { } public static void main(String[] args) { try { MyResourceOut resource = new MyResourceOut(); try { resource.out(); } catch (Throwable var5) { try { resource.close(); } catch (Throwable var4) { var5.addSuppressed(var4); } throw var5; } resource.close(); } catch (Exception var6) { var6.printStackTrace(); } } }
这次,catch 块中主动调用了 resource.close(),并且有一段很关键的代码 var5.addSuppressed(var4)。它有什么用处呢?当一个异常被抛出的时候,可能有其他异常因为该异常而被抑制住,从而无法正常抛出。这时可以通过 addSuppressed() 方法把这些被抑制的方法记录下来。被抑制的异常会出现在抛出的异常的堆栈信息中,也可以通过 getSuppressed() 方法来获取这些异常。这样做的好处是不会丢失任何异常,方便我们开发人员进行调试。
哇,有没有想到我们之前的那个例子——在 try-finally 中,readLine() 方法的异常信息竟然被 close() 方法的堆栈信息吃了。现在有了 try-with-resources,再来看看作用和 readLine() 方法一致的 out() 方法会不会被 close() 吃掉。
在 close() 和 out() 方法中直接抛出异常:
class MyResourceOutThrow implements AutoCloseable { @Override public void close() throws Exception { throw new Exception("close()"); } public void out() throws Exception{ throw new Exception("out()"); } }
调用这 2 个方法:
public class TrywithresourcesCustomOutThrow {
public static void main(String[] args) {
try (MyResourceOutThrow resource = new MyResourceOutThrow();) {
resource.out();
} catch (Exception e) {
e.printStackTrace();
}
}
}
程序输出的结果如下所示:
java.lang.Exception: out() at com.cmower.dzone.trycatchfinally.MyResourceOutThrow.out(TrywithresourcesCustomOutThrow.java:20) at com.cmower.dzone.trycatchfinally.TrywithresourcesCustomOutThrow.main(TrywithresourcesCustomOutThrow.java:6) Suppressed: java.lang.Exception: close() at com.cmower.dzone.trycatchfinally.MyResourceOutThrow.close(TrywithresourcesCustomOutThrow.java:16) at com.cmower.dzone.trycatchfinally.TrywithresourcesCustomOutThrow.main(TrywithresourcesCustomOutThrow.java:5)
瞧,这次不会了,out() 的异常堆栈信息打印出来了,并且 close() 方法的堆栈信息上加了一个关键字 Suppressed。一目了然,不错不错,我喜欢。
总结一下,在处理必须关闭的资源时,始终有限考虑使用 try-with-resources,而不是 try–catch-finally。前者产生的代码更加简洁、清晰,产生的异常信息也更靠谱。答应我好不好?别再用 try–catch-finally 了。
觉得有点用记得给我点赞哦!😎
简单介绍一下。我是沉默王二,一枚有趣的程序员。10 年前,当我上大学的时候,专业被调剂到了计算机网络,主修 Java 编程语言,但当时没怎么好好学(因为第一次接触计算机,感觉太难了),每年都要挂科两三门;因此工作后吃了不少亏。但是最近几年,情况发生了很大改变,你应该也能看得到我这种变化。通过坚持不懈地学习,持续不断地输出,我的编程基本功算得上是突飞猛进。
为了帮助更多的程序员,我创建了“沉默王二”这个 ID,专注于分享有趣的 Java 技术编程和有益的程序人生。一开始,博客的阅读量寥寥无几,关注人数更是少得可怜。但随着影响力的逐步扩大,阅读量和关注人都在猛烈攀升。
你在看这篇文章的时候,应该也能发现,我在 CSDN 上的总排名已经来到了第 71 位,这个排名还是非常给力的。有很多读者都说,我可以冲击第一名,我不愿意藏着掖着,我是有这个野心的。如果你也喜欢我的文章,请记得微信搜索「沉默王二」关注我的原创公众号,回复“1024”更有美团技术大佬整理的 Java 面试攻略相送,还有架构师的面试视频哦。绝对不容错过,期待与你的不期而遇。