自动调用关闭释放资源try-with-resources
try-with-resources自动执行释放资源
看到了try这个关键字立马就应该能想到异常处理机制try-catch-finally语句块。这里要说的东西和异常处理背后的机制其实几乎是一样的,只不过try-with-resources侧重点异常后自动释放资源,不需要我们手动去在调用close()方法。后面会从JLS层面,以及从字节码层面举例详细说明。
做什么用的
try-with-resources语句是用变量(称为资源)来参数化的,这些变量在try块执行之前被初始化,并在try块执行后以初始化的相反顺序自动关闭。当资源自动关闭时,catch子句和finally子句通常是不必要的。
一句话就是用来自动调用关闭方法,释放资源。
Java语言规范(JLS)是如何定义的
- 在资源规范中声明的变量类型必须是AutoCloseable的子类型,否则会发生编译时错误
- 多个资源使用';'号分割,也就说try语句块中可以写多个资源初始化。
- 不能有重名的变量名,否则编译报错
- 在资源规范中声明的变量如果没有显式声明为final,则隐式声明为final
有哪些使用姿势
- 基本使用方法,只需try(){}语句块即可
public class FileWriter implements AutoCloseable{
@Override
public void close() {
System.out.println("file writer close");
} public void writeFile(String s) {
System.out.println("file writer write" + s);
}
}
//这里举例一个类实现了AutoCloseable接口,然后,我们就可以直接使用try资源语句块来包装它,
//使用完不需要去手动去close(),会自动调用close方法。
try (
FileWriter writer = new FileWriter();
) {
writer.writeFile("target.cs");
}
//多个子句也是一样,关闭的顺序是反着来。如下会先调用reader.close(),然后是writer.close()
try (
FileWriter writer = new FileWriter();
FileReader reader = new FileReader();
) { writer.writeFile("target.cs");
reader.readFile("target.cs");
}
- 可以结合catch,finally像异常处理一样。嵌套什么的,也没问题
try (FileWriter writer = new FileWriter()) {
writer.writeFile("target.cs");
try(FileReader reader = new FileReader()) {
reader.readFile("target.cs");
}
}catch (Exception e) {
//do exception
}
从字节码层面详细说明JVM是如何解析和执行的
我们没有主动调用close()方法,那是何时谁调用的close呢,我们从编译后的字节码中就可以看到
假设源码如下:非常的简单,FileWriter这个类没有贴出,就是像上面的一样实现了AutoCloseable接口,然后自定义了一个writeFile方法。
public class AutoClose {
public static void main(String[] args) {
try (FileWriter writer = new FileWriter()) {
writer.writeFile("target.cs");
}
}
}
编译后字节码展示如下:

重点说明:
我这里按照字节码序号,也就是自然顺序号(也就是第一列)[第二列是PC号]
- 可以看到第15行出现了一句,invokevirtual 字节码指令,调用了FileWriter.close()方法。
- 另外第23行也出现了一模一样的字节码指令。这是为了处理即使异常情况下,close方法也要正常调用。
- 如下是异常表:

也就是说,即使调用writeFile方法异常了,也要自动调用关闭方法,所以可以看到异常表PC号是814。异常表的第二行,解释大白话就是如果close方法异常了,那就把异常加入到异常列表中,因此看到的PC号是2226。最终是将异常抛出。 - 粉色的+19、+9那些表示的是字节码偏移量 (当前PC号加括号中的)
多个资源列表的时候等于是多个catch一样,只要初始化成功的,无论执行业务方法是否异常,都会调用它的close方法。
try-with-resources优先于try-finally
这个原则在Effective Java中也有说明。尤其是当语句块中有多个资源需要处理关闭操作的时候,嵌套try-finally语句,很可能会导致异常被抹除。而使用try-with-resources即使多个异常被禁止时,仍然可以使用getSuppresed方法访问到它们
自动调用关闭释放资源try-with-resources的更多相关文章
- 根据判断PC浏览器类型和手机屏幕像素自动调用不同CSS的代码
1.媒体查询方法在 css 里面这样写 -------------------- @media screen and (min-width: 320px) and (max-width: 480px) ...
- paintEvent(QPaintEvent*)是系统自动调用的
qt中函数paintEvent(QPaintEvent*)是被系统自动调用. paintEvent(QPaintEvent *)函数是QWidget类中的虚函数,用于ui的绘制,会在多种情况下被其他函 ...
- QT5.3无法自动调用incomingConnection函数的问题(4.7没有这个问题)
最近将qt4.7的一个工程移到5.3,遇到了几个麻烦事,主要是这个incomingConnection监听后无法自动调用的问题,在4.7上是完全没有问题的,到了5.3就不行,网上也查了下,网友们都是放 ...
- 如果浏览器自动调用quirks模式打开的话
(从已经死了一次又一次终于挂掉的百度空间人工抢救出来的,发表日期 2014-03-21) 则肯定你的html的声明,没有写好. 今天遇到几个,前面莫名其妙的多了个空格(在网页上看源码是多空格,复制到n ...
- PHP中 对象自动调用的方法:__set()、__get()、__tostring()
总结: (1)__get($property_name):获取私有属性$name值时,此对象会自动调用该方法,将属性name值传给参数$property_name,通过这个方法的内部 执行,返回我们传 ...
- C++构造函数的自动调用(调用一个父类的构造函数,有显性调用最好,否则就默认调用无参数的构造函数)——哲学思想:不调用怎么初始化父类的成员数据和VMT?
我总是记不住构造函数的特点,关键还是没有领会那个哲学思想:父类的构造函数一方面要初始化它自己的成员数据,另一方面也要建立它自己的VMT呀!心里默念一百遍:一定调用父类构造函数,一定调用父类构造函数,一 ...
- Object之魔术函数__toString() 直接输出对象引用时自动调用
__toString()是快速获取对象的字符串信息的便捷方式 在直接输出对象引用时自动调用的方法. __toString()的作用 当我们调试程序时,需要知道是否得出正确的数据.比如打印一个对象时,看 ...
- QT5.3无法自动调用incomingConnection函数的问题
最近将qt4.7的一个工程移到5.3,遇到了几个麻烦事,主要是这个incomingConnection监听后无法自动调用的问题,在4.7上是完全没有问题的,到了5.3就不行,网上也查了下,网友们都是放 ...
- 当使用System,out.println()打印一个对象是自动调用toString方法
在Java中,所有的对象都是继承自Object,自然继承了toString方法,在当使用System,out.println()里面为一个对象的引用时,自动调用toString方法讲对象打印出来.如果 ...
- PHP 命名空间以及自动加载(自动调用的函数,来include文件)
这篇文章的目的是记录 1. php中的自动加载函数 __autoload(), 和 spl_autoload_register()函数, 2 .php中命名空间的使用. 一.当不使用命名空间的时候 a ...
随机推荐
- Log4Net配置详解及输出自定义消息类示例
1.简单使用实例 1.1 添加log4net.dll的引用. 在NuGet程序包中搜索log4net并添加,此次我所用版本为2.0.17.如下图: 1.2 添加配置文件 右键项目,添加新建项, ...
- spring cloud 上云的情况下,Ribbon 客户端负载均衡 与 ALB 服务端负载均衡的选择
在云环境(例如AWS)中,由于云提供商通常提供强大的负载均衡服务(如AWS的ALB),一般不再需要使用Ribbon这种客户端负载均衡方案.云环境中的负载均衡器通常能够提供更高的可靠性.可扩展性和简化的 ...
- 测试人必会 K8S 操作之 Dashboard
在云计算和微服务架构的时代,Kubernetes (K8S) 已成为管理容器化应用的标准.然而,对于许多新手来说,K8S 的操作和管理常常显得复杂而神秘.特别是,当你第一次接触 K8S Dashboa ...
- AI驱动音乐创新,网易数帆X云音乐刷新MIREX世界纪录 网易数帆 网易数帆
在近期揭榜的2021国际音频检索评测大赛(MIREX)上,网易数帆易智语音团队携手网易云音乐音视频实验室,凭借生产级AI技术创新能力,在歌词识别和歌单识别两个赛道大幅打破世界纪录夺得冠军. MIREX ...
- [oeasy]python0094_视频游戏_双人网球_pong_atari_mos_6502_雅达利_米洛华
编码进化 回忆上次内容 上次 我们回顾了 微软之前的 比尔盖茨和保罗艾伦 mits 迎来的 是帮手 还是隐患? intel-8080 遇到了 mos-6502 底层硬件 驱动 游戏行业进化 不光是扑克 ...
- C# Expression详解(高级)
LINQ在本地查询IEnumerbale主要是用委托来作为传参,而解析型查询IQueryable则用Expression来作为传参: public static IEnumerable<T> ...
- 使用 @Audited 增强Spring Boot 应用程序的数据审计能力
介绍 在Spring Boot开发的动态世界中,确保数据完整性和跟踪变化是至关重要的.实现这一目标的一个强大工具是@Audited注解.本文深入探讨了该注解的复杂性.其目的.实现步骤以及如何利用其功能 ...
- 小狼毫&雾凇拼音安装及部署-Windows(图文)
小狼毫输入法和雾凇拼音主题安装以及配置步骤 先上资源链接 小狼毫官网:RIME | 中州韻輸入法引擎 小狼毫Github地址:rime/weasel: [小狼毫]Rime for Windows (g ...
- redis环境的安装
Redis环境的安装(源码安装),主要分为单机安装与集群安装,无论是单机安装还是集群安装,Redis本身的依赖是必须要有的,本文所采用的Redis版本是redis-5.0.3,所需要的依赖如下: cp ...
- UDP协议测试
UDP协议测试 我们一般想到测试连通性时第一考虑到的就是使用ping命令. 但是我们知道ping命令使用的是icmp协议,属于tcp/ip协议中的一个子协议,所以我们可以用ping或tcping命令来 ...