2019独角兽企业重金招聘Python工程师标准>>>

1、旧社会

Java里,对于文件操作IO流、数据库连接等开销非常昂贵的资源,用完之后必须及时通过close方法将其关闭,否则资源会一直处于打开状态,直至程序停止,增加系统负担。

关闭资源的常用方式就是在finally块里是释放,即调用close方法。比如,我们经常会写这样的代码:

public static void main(String[] args) {BufferedReader br = null;try {String line;br = new BufferedReader(new FileReader("d:\\testing.txt"));while ((line = br.readLine()) != null) {System.out.println(line);}} catch (IOException e) {// handle exception} finally {try {if (br != null) {br.close();}} catch (IOException ex) {// handle exception}}
}

可以看出,为了关闭资源以及处理关闭资源时可能出现的异常,不得不写一大推代码。

2、新时代

2.1 使用新写法

从Java 7开始,jdk提供了一种更好的方式关闭资源,使用try-with-resources语句,改写一下上面的代码,效果如下:

public static void main(String[] args) {try(BufferedReader br = new BufferedReader(new FileReader("d:\\testing.txt"))) {String line;while ((line = br.readLine()) != null) {System.out.println(line);}} catch (IOException e) {// handle exception}
}

清爽了很多是不是? 但是,有没有一点不安呢?

2.2 新问题

原来释放资源的时候如果发生异常,我们可以在finally块中catch新异常,然后继续处理。但是新方式没有了finally块,异常是如何抛出的?如果关闭资源时发生异常怎么办?我们怎么处理?

从文档上可以找到这样一段描述:

If an exception is thrown from the try block and one or more exceptions are thrown from the try-with-resources statement, then those exceptions thrown from the try-with-resources statement are suppressed. You can retrieve these suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block.

意思是:如果 try 块抛出异常并且 try-with-resources 语句抛出一个或多个异常,那么从 try-with-resources 语句中抛出的异常将会被忽略。你可以通过调用由 try块抛出的异常的Throwable.getSuppressed 方法检索这些被忽略的异常信息。

在明确一点说就是:

  • 如果try块异常,catch到的是try块抛出的异常;
  • 如果try块正常,close异常,catch到的是close抛出的异常;
  • 如果try块异常,close也异常,catch到的是try块抛出的异常,close异常被忽略。

基于这几种情况,我们做几个测试分别验证一下:

2.2.1 try块异常

大家都懂,略。

2.2.2 try块正常,close异常

public class TestTryWithResources {public static void main(String[] args) {try (MyResource resource = new MyResource()) {} catch (Exception e) {System.out.println("捕获异常: " + e.getMessage());}}
}/*** 自定义一个资源类,close时抛出异常** ps:只有实现AutoCloseable或Closeable接口的对象才能用try-with-resources*/
class MyResource implements AutoCloseable {@Overridepublic void close() throws Exception {System.out.println("执行close方法,释放资源");throw new Exception("释放资源异常");}
}

执行结果为: 执行close方法,释放资源 捕获异常: 释放资源异常

即,catch到的是close方法抛出的异常

2.2.3 try块异常,close也异常

public class TestTryWithResources {public static void main(String[] args) {try (MyResource resource = new MyResource()) {throw new Exception("try块异常");} catch (Exception e) {System.out.println("捕获异常: " + e.getMessage());// 找到被忽略的异常Throwable[] ts = e.getSuppressed();for(Throwable t : ts) {System.out.println("被忽略的异常"+ t.getMessage());}}}
}/*** 自定义一个资源类,close时抛出异常*/
class MyResource implements AutoCloseable {@Overridepublic void close() throws Exception {System.out.println("执行close方法,释放资源");throw new Exception("释放资源异常");}
}

执行结果: 执行close方法,释放资源 捕获异常: try块异常 被忽略的异常: 释放资源异常

即,catch到的是try块中的异常,释放资源时产生的异常被忽略了。

2.3 实践中的问题

实际上,很多时候try块中的异常和close方法抛出的异常是同一类型的。比如流、网络等不论是try块还是close方法都是抛出IOException,我们该怎么办? 最佳实践:按异常栈最底层的方法名判断。如果是close方法抛出的异常,就是关闭资源时产生的。 注:我们的方法名不能叫close

public class TestTryWithResources {public static void main(String[] args) {try (MyResource resource = new MyResource()) {throw new Exception("try块异常");} catch (Exception e) {if(!"close".equals(e.getStackTrace()[0].getMethodName())){System.out.println("处理业务异常");}}}
}/*** 自定义一个资源类,close时抛出异常*/
class MyResource implements AutoCloseable {@Overridepublic void close() throws Exception {System.out.println("执行close方法,释放资源");throw new Exception("释放资源异常");}
}

转载于:https://my.oschina.net/u/145060/blog/701357

使用try-with-resources替代try finally释放资源相关推荐

  1. PEP 8 – Style Guide for Python Code

    PEP 8 – Style Guide for Python Code PEP 8–Python编码规范 原文地址:https://www.python.org/dev/peps/pep-0008/ ...

  2. springboot怎么替代jsp_如何在SpringBoot中使用JSP ?但强烈不推荐,果断改Themeleaf吧...

    做WEB项目,一定都用过JSP这个大牌.Spring MVC里面也可以很方便的将JSP与一个View关联起来,使用还是非常方便的.当你从一个传统的Spring MVC项目转入一个Spring Boot ...

  3. Android之Providing Resources(提供资源)

    当你写程序的时候应该习惯于把一些程序需要用到的资源,例如图片和字符串,分开并独立地保存在你的程序代码之外,这样你就可以独立地维护这些资源文件.你还应该通过特殊的名字的文件路径,为特定的设备配置提供可替 ...

  4. SpringMVC 的使用映射路径 mvc:resources

    以下是测试结果,可能存在纰漏,暂记录一下. 使用springMVC时,一般将DispatcherServlet请求映射配置为"/",则Spring MVC将捕获Web容器所有的请求 ...

  5. Spring5参考指南: Resources

    文章目录 内置Resource实现 ResourceLoader ResourceLoaderAware 资源作为依赖 构造ClassPathXmlApplicationContext-快捷方式 资源 ...

  6. 如何编写数据库可视化界面_编写用于数据可视化的替代文本

    如何编写数据库可视化界面 什么是替代文字 (What is Alt Text) Alt text (sometimes called Alt tags or alternative text) are ...

  7. [设计模式] ------ 策略模式实战:java中替代if-else的大段逻辑

    java中用策略模式替代if-else的大段逻辑 问题: java本来是一门以面向对象为主的语言,但很多人嘴上说着java面向对象,然后除了表映射实体之外,其他的还是面向过程的思路. 就比如今天要说的 ...

  8. ai人工智能将替代人类_AI和人类如何优化空气污染监测

    ai人工智能将替代人类 空气污染监测 (Air-pollution monitoring) Air pollution is responsible for 4.2 million deaths pe ...

  9. 100个替代昂贵商业软件的开源应用/100 Open Source Replacements for Expensive Applications

    100 Open Source Replacements for Expensive Applications Enterprises, SMBs and home users can see sig ...

最新文章

  1. 第三方医药物流的现状及发展
  2. SQL Server 中的事务和锁(三)-Range S-U,X-X 以及死锁
  3. Linux服务器安全防护十个方面
  4. Unreal Engine 4切换默认Camera实现
  5. HDFS与MapReduce
  6. MySQL之级联删除、级联更新、级联置空
  7. [USACO12FEB]附近的牛Nearby Cows
  8. SourceTree 密码填写正确但是拉取显示密码错误解决
  9. Python自然语言处理学习笔记(64): 7.5 命名实体识别
  10. 人生的意义,在于不断地超越自己
  11. ET1100和PHY的总结
  12. es6中的静态属性和方法
  13. 介绍一个开源博客项目并部署到Nginx服务器
  14. python背景颜色代码大全_python3中布局背景颜色代码分析
  15. getActionCommand()方法具体含义?
  16. CCF CSP 行车路线 java 201712_4
  17. P4606 [SDOI2018]战略游戏
  18. 氖星数字人口型、动作、表情接口
  19. vscode的下载速度会特别慢问题处理
  20. 新华三H3CMagic系列路由器获取不到IPV6地址解决方法

热门文章

  1. 怎样在数组末尾添加数据_如何利用C++实现可变长的数组?
  2. leetcode914. 卡牌分组
  3. 关系数据库——范式/反范式的利弊权衡和建议
  4. 深度学习(09)-- DenseNet
  5. python数组初始化_Python Numpy 数组的初始化和基本操作
  6. 英语口语week 14 Thursday
  7. 互联网产品用户体验设计的三大定律
  8. GCC笔记 命令行分析
  9. H.263 H.263+ Payload Type
  10. java 中 transient关键字