使用try-with-resources替代try finally释放资源
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释放资源相关推荐
- 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/ ...
- springboot怎么替代jsp_如何在SpringBoot中使用JSP ?但强烈不推荐,果断改Themeleaf吧...
做WEB项目,一定都用过JSP这个大牌.Spring MVC里面也可以很方便的将JSP与一个View关联起来,使用还是非常方便的.当你从一个传统的Spring MVC项目转入一个Spring Boot ...
- Android之Providing Resources(提供资源)
当你写程序的时候应该习惯于把一些程序需要用到的资源,例如图片和字符串,分开并独立地保存在你的程序代码之外,这样你就可以独立地维护这些资源文件.你还应该通过特殊的名字的文件路径,为特定的设备配置提供可替 ...
- SpringMVC 的使用映射路径 mvc:resources
以下是测试结果,可能存在纰漏,暂记录一下. 使用springMVC时,一般将DispatcherServlet请求映射配置为"/",则Spring MVC将捕获Web容器所有的请求 ...
- Spring5参考指南: Resources
文章目录 内置Resource实现 ResourceLoader ResourceLoaderAware 资源作为依赖 构造ClassPathXmlApplicationContext-快捷方式 资源 ...
- 如何编写数据库可视化界面_编写用于数据可视化的替代文本
如何编写数据库可视化界面 什么是替代文字 (What is Alt Text) Alt text (sometimes called Alt tags or alternative text) are ...
- [设计模式] ------ 策略模式实战:java中替代if-else的大段逻辑
java中用策略模式替代if-else的大段逻辑 问题: java本来是一门以面向对象为主的语言,但很多人嘴上说着java面向对象,然后除了表映射实体之外,其他的还是面向过程的思路. 就比如今天要说的 ...
- ai人工智能将替代人类_AI和人类如何优化空气污染监测
ai人工智能将替代人类 空气污染监测 (Air-pollution monitoring) Air pollution is responsible for 4.2 million deaths pe ...
- 100个替代昂贵商业软件的开源应用/100 Open Source Replacements for Expensive Applications
100 Open Source Replacements for Expensive Applications Enterprises, SMBs and home users can see sig ...
最新文章
- 第三方医药物流的现状及发展
- SQL Server 中的事务和锁(三)-Range S-U,X-X 以及死锁
- Linux服务器安全防护十个方面
- Unreal Engine 4切换默认Camera实现
- HDFS与MapReduce
- MySQL之级联删除、级联更新、级联置空
- [USACO12FEB]附近的牛Nearby Cows
- SourceTree 密码填写正确但是拉取显示密码错误解决
- Python自然语言处理学习笔记(64): 7.5 命名实体识别
- 人生的意义,在于不断地超越自己
- ET1100和PHY的总结
- es6中的静态属性和方法
- 介绍一个开源博客项目并部署到Nginx服务器
- python背景颜色代码大全_python3中布局背景颜色代码分析
- getActionCommand()方法具体含义?
- CCF CSP 行车路线 java 201712_4
- P4606 [SDOI2018]战略游戏
- 氖星数字人口型、动作、表情接口
- vscode的下载速度会特别慢问题处理
- 新华三H3CMagic系列路由器获取不到IPV6地址解决方法