java中的try-with-resource语法
java的世界千奇百怪。。。当我甩出如下代码段,不知阁下如何应对?
try(A a=new A()){
和a变量无关的业务代码块
}
没错,这就是“臭名昭著”的try-with-resource语法,乍一看让人不知所云,其实它和try-finally的下述代码等价
A a=new A()
try{
//业务代码块
}finally{
a.close();
}
本质上就是当使用 try-with-resources 语句块来处理实现了 AutoCloseable 接口的资源时,Java 编译器会在生成的字节码中进行特殊处理。编译器会自动在 try 块结束时插入 finally 块,并在 finally 块中调用 close() 方法来关闭资源。
try-with-resources语法
try-with-resources 语句是一个 Java 7 引入的语法结构,用于自动关闭实现了 AutoCloseable 或 Closeable 接口的资源。它的语法形式如下:
try (resource_declaration) {
// 使用资源的代码块
} catch (ExceptionType e) {
// 异常处理逻辑
}
在 try-with-resources 语句中,resource_declaration 部分用于声明和初始化一个或多个资源对象。这些资源对象必须实现 AutoCloseable 或 Closeable 接口。
在 try 代码块中,可以使用这些资源对象进行操作。当 try 代码块执行结束时,不论是正常结束还是发生异常,都会自动调用资源对象的 close() 方法来关闭资源。
如果同时声明了多个资源对象,可以使用分号 ; 分隔它们。
那么,它和try-finally语句有什么区别呢?
和try-finally的关系
很明显,try-with-resource语法相对于try-finally语法来说,隐式的调用了资源对象的close方法,语法更简洁,其次,让我们看看如下代码块:
@Test
public void testException(){
try{
throw new CustomException("代码块内的业务异常");
}finally {
throw new CustomException("finally中的资源释放异常");
}
}
运行上面的代码,你将会得到如下异常:

模仿上述代码,看看在try-with-resource语法中又会怎样
先创建一个类MyAutoClose
@Slf4j
public class MyAutoClose implements AutoCloseable {
@Override
public void close() throws Exception {
log.info("自动关闭");
throw new CustomException("close方法异常");
}
}
运行如下单元测试
@Test
public void testAutoClose() {
try (MyAutoClose autoClose = new MyAutoClose()) {
throw new CustomException("业务异常");
} catch (Exception e) {
log.error("", e);
}
}
得到如下异常

综合两种结果来看,可以看到同样的逻辑,业务和finally都是抛出了异常,但是抛出的异常却不一样:在try-finally语句块中,抛出的是finally中的异常,在try-with-resource语句块中,抛出的是业务的异常,而且异常中还携带了close方法关闭时抛出的异常信息。
谁好谁坏,自行体会。
try-with-resources的本质
再进一步细想一下,为啥两种方式逻辑基本一样,但是抛出的异常却不一样?
try-finally代码块很直观,try-with-resource代码块在编译成字节码文件的时候却被编译期“魔改”了,上文提到过
......Java 编译器会在生成的字节码中进行特殊处理。编译器会自动在
try块结束时插入finally块,并在finally块中调用close()方法来关闭资源。
那只需要通过反编译看下class文件就可以了

再回想一下它原来长什么样子
@Test
public void testAutoClose() {
try (MyAutoClose autoClose = new MyAutoClose()) {
throw new CustomException("业务异常");
} catch (Exception e) {
log.error("", e);
}
}
亲妈都认不出来了。。。
我将反编译后的真正代码分成了四部分,并标记在了图上
- 外层异常try-catch块尝试捕获初始化资源异常
- 里层try-catch块尝试捕获业务执行异常
- 业务try-catch块捕获到异常,直接抛出
- finally块判定是否发生了业务异常:如果发生了业务异常,而且close方法执行也发生了异常,则将close方法发生的异常附加业务异常中;如果未发生业务异常,则直接执行close方法,这时候如果发生了异常,直接抛出的就是finally块中的异常了。
总结下,实际上是如下形式
try{
//初始化资源
try{
//业务代码执行
}catch(Exceptin e){
//捕获的业务异常,抛出业务异常
}finally{
//执行close方法,并判定在不同情况下的异常信息
}
}catch(Exception e){
//捕获的资源初始化异常
}
结论:使用try-with-resource很明显比使用try-finally块要更好一些,它能准确捕获业务异常;但是try-finally块也有不可替代的使用场景,比如资源类未实现AutoCloseable接口的时候
最后,欢迎关注我的博客原文:https://blog.kdyzm.cn/post/179
END.
java中的try-with-resource语法的更多相关文章
- java中根据key获取resource下properties资源文件中对应的参数
properties资源文件是放在resource目录下的: 新建工具类: package com.demo.utils; import java.io.InputStream; import jav ...
- JAVA中abstract,interface,final,static语法
转自:http://www.cnblogs.com/yueue/archive/2010/04/20/1715863.html 一,抽象类:abstract 1,只要有一个或一个以上抽象方法的 ...
- java中带参数的try(){}语法
带资源的try语句(try-with-resource)的最简形式为: try(Resource res = xxx)//可指定多个资源 { work with res } try块退出时,会自动调用 ...
- java 中的异常处理
一. 异常的概念和Java异常体系结构 异常是程序运行过程中出现的错误.本文主要讲授的是Java语言的异常处理.Java语言的异常处理框架, 是Java语言健壮性的一个重要体现. Java把 ...
- Java 中 JDBC 基础配置
Java 中 JDBC 基础配置 <resource auth="Container" driverclassname="oracle.jdbc.driver.Or ...
- Java中的java.lang.Class API 详解
且将新火试新茶,诗酒趁年华. 概述 Class是一个位于java.lang包下面的一个类,在Java中每个类实例都有对应的Class对象.类对象是由Java虚拟机(JVM)自动构造的. Class类的 ...
- Java中的方法和方法重载
上次我们讲了Java中的一些基本的语法;今天我们就讲一点内容,来说说Java中的方法和方法重载以及需要注意的一些地方; 方法: Java的方法类似与其他语言的函数,是一段用来完成特定功能的代码片段, ...
- java中异常的抛出:throw throws
java中异常的抛出:throw throws Java中的异常抛出 语法: public class ExceptionTest{ public void 方法名(参数列表) throws 异常列表 ...
- Java 中多态的实现(下)
Java 中多态的另一个语法实现是重写.重载是通过静态分派实现的,重写则是通过动态分派实现的. 在学习动态分派之前,需要对虚拟机的知识有一个初步的了解. 虚拟机运行时数据区 运行 Java 程序时,虚 ...
- Java中的10颗语法糖
语法糖(Syntactic Sugar):也称糖衣语法,指在计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用.通常来说,使用语法糖能够增加程序的可读性,减少程序代码出错的 ...
随机推荐
- Jenkins远程执行shell脚本,超时报错(ERROR: Exception when publishing, exception message [Exec timed out or was interrupted after 120,001 ms])
通过Jenkins远程执行脚本时,发现Jenkins构建任务失败,但是服务器本身的脚本是生效的. 排查确认是Jenkins构建任务超时,导致Jenkins看板显示任务构建失败,但是服务器上的自动脚本执 ...
- 关于package-lock.json
前言 上篇文章我们了解了package.json,一般与它同时出现的还有一个package-lock.json,这两者又有什么关系呢?下面一起来了解吧. 介绍 package-lock.json 它会 ...
- DASCTF 2023 & 0X401七月暑期挑战赛
比赛只出了一道,小菜不是罪过-_- controlflow 这个题动调到底就行 for i in range(40): after_xor[i]=inp[i]^0x401 after_xor[i] + ...
- BUUCTF-RE-[BJDCTF2020]BJD hamburger competition
啊这,点进去康康 dnspy反编译的题,https://www.52pojie.cn/thread-495115-1-1.html 里面有详细介绍 然后文件很多,我不知道找哪一个下手 看其他师傅的wp ...
- Java应用堆外内存泄露问题排查
问题是怎么发现的 最近有个java应用在做压力测试 压测环境配置: CentOS系统 4核CPU 8g内存 jdk1.6.0_25,jvm配置-server -Xms2048m -Xmx2048m 出 ...
- 7、Spring之基于注解管理bean
本质上:所有一切的操作都是Java代码来完成的,XML和注解只是告诉框架中的Java代码如何执行. 7.1.环境搭建 创建名为spring_ioc_annotation的新module,过程参考3.1 ...
- CodeForces 1367D Task On The Board
题意 给一个字符串\(t\),和一个长度为\(m\)的数组\(b[]\),要求构造一个字符串\(s\),\(s\)中的字符都出现在\(t\)中,对于\(s[i]\)而言,对于任意\(j\),如果有\( ...
- Docker 镜像库国内加速的几种方法
概述 在国内,拉取 Docker 镜像速度慢/时不时断线/无账号导致限流等,比较痛苦. 这里提供加速/优化的几种方法. 梳理一下,会碰到以下情况: 国内下载速度慢/时不时断线:是因为网络被限制了. 没 ...
- KRpano项目微信出现"关于潜在的违法或违规内容"
最近,部分小伙伴反应某些KRPano项目在微信中,出现"关于潜在的未发或违规内容"而无法播放的问题,会看到下图中的提示: 出现原因 这个问题是由于KRPano项目中的webvr.j ...
- Solution -「POJ 1322」Chocolate
Description Link. 包里有无穷多个巧克力,巧克力有 \(c\) 种颜色,每次从包里拿出不同颜色巧克力的概率都是相等的,桌面的巧克力不允许颜色相同,若某次拿出的巧克力与桌上的巧克力颜色相 ...