try-catch-finally 和 try-with-resources

try-catch-finally 与 try-with-resources的区别 浅谈try-catch-finally 与 try-with-resources的区别 阅读详情

一、简述

如果在 try 语句块里使用 return 语句,那么 finally 语句块还会执行吗?答案是肯定的。Java 官方文档上是这么描述的:The finally block always executes when the try block exits.。描述词用的是 always,即在 try 执行完成之后,finally 是一定会执行的。这种特性可以让程序员避免在 try 语句中使用了return、continue 或者 break 关键字而忽略了关闭相关资源的操作。把清理相关资源放到 finally 语句块中一直是最佳实践。

ps:用到 finally 关闭资源的时候,应该尽量避免在 finally 语句块中出现运行时错误,可以适当添加判断语句以增加程序健壮性:

finally {
  if (out != null) { 
     System.out.println("Closing PrintWriter");
     out.close(); // 不要在finally语句中直接调用close()
   } else { 
     System.out.println("PrintWriter not open");
   } 
}
  1. 不管有木有出现异常,finally 块中代码都会执行。
  2. 当 try 和 catch 中有 return 时,finally 仍然会执行。
  3. finally 是在 return 后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来【先存到一个本地变量中】,不管 finally 中的代码怎么样,返回的值都不会改变,仍然是之前保存的值),所以函数返回值是在 finally 执行前确定的。
  4. finally 中最好不要包含 return,否则程序会提前退出,返回值不是 try 或 catch 中保存的返回值。因为规范规定了,当 try 和 finally 里都有 return 时,会忽略 try 的 return,而使用 finally 的 return。

二、应用场景

1️⃣try{} catch(){}finally{} return;
显然程序按顺序执行。
2️⃣try{ return; }catch(){} finally{} return;
程序执行 try 块中 return 之前(包括 return 语句中的表达式运算)代码;
再执行 finally 块,最后执行 try 中 return;
finally 块之后的语句 return,因为程序在 try 中已经 return 所以不再执行。
3️⃣try{ } catch(){return;} finally{} return;
程序先执行 try,如果遇到异常执行 catch 块,
有异常:则执行 catch 中 return 之前(包括 return 语句中的表达式运算)代码,再执行 finally 语句中全部代码,最后执行 catch 块中 return。finally 之后也就是4处的代码不再执行。
无异常:执行完 try 再 finally 再 return。
4️⃣try{ return; }catch(){} finally{return;}
程序执行 try 块中 return 之前(包括 return 语句中的表达式运算)代码;
再执行 finally 块,因为 finally 块中有 return 所以提前退出。
5️⃣try{} catch(){return;}finally{return;}
程序执行 catch 块中 return 之前(包括 return 语句中的表达式运算)代码;
再执行 finally 块,因为 finally 块中有 return 所以提前退出。
6️⃣try{ return;}catch(){return;} finally{return;}
程序执行 try 块中 return 之前(包括 return 语句中的表达式运算)代码;
有异常:执行 catch 块中 return 之前(包括 return 语句中的表达式运算)代码;则再执行 finally 块,因为 finally 块中有 return 所以提前退出。
无异常:则再执行 finally 块,因为 finally 块中有 return 所以提前退出。

三、小结

1️⃣如果 finally 存在的话,任何执行 try 或者 catch 中的 return 语句之前,都会先执行 finally 语句。
2️⃣如果 finally 中有 return 语句,那么程序就 return 了。所以 finally 中的 return 是一定会被 return 的,编译器把 finally 中的 return 实现为一个 warning。

public class FinallyTest {
public static void main(String[] args) {
    System.out.println(new FinallyTest().test());;
}
static int test(){
    int x = 1;
    try{
        x++;
        return x;
    }finally{
        ++x;
        }
      }
  }

结果是2。
分析:在 try 语句中,在执行 return 语句时,要返回的结果已经准备好了,就在此时,程序转到 finally 执行了。在转去之前,try 中先把要返回的结果存放到不同于 x 的【局部变量】中去,执行完 finally 之后,在从中取出返回结果。因此,即使 finally 中对变量 x 进行了改变,但是不会影响返回结果。它应该使用栈保存返回值。

四、自动资源管理(Automatic Resource Management)

在 JDK1.7 前,通常使用 try{}catch() 来捕获异常的,如果遇到类似 IO 流的处理,一般是在 finally 部分关闭 IO 流。但在 JDK1.7 后,Java 7 的编译器和运行环境支持新的 try-with-resources 语句,称为 ARM 块。写在()里面的流对象对应的类都实现了自动关闭接口 AutoCloseable。

1️⃣认识java.lang.AutoCloseable接口

JDK1.7 之前,通过 try{} finally{} 在 finally 中释放资源。在 finally 中关闭资源存在以下问题:

  1. 开发者需要手动写代码做关闭的逻辑。
  2. 有时候可能会忘记关闭一些资源,导致内存泄漏。
  3. 关闭代码的逻辑比较冗长,代码可读性差。

在 JDK1.7 后,对于实现 AutoCloseable 接口的类的实例,将其放到 try 后面(称之为:带资源的 try 语句),在 try 结束的时候,会自动将这些资源关闭(调用 close 方法)。带资源的 try 语句的 3 个关键点:

  1. 由带资源的 try 语句管理的资源必须是实现了 AutoCloseable 接口的类的对象。
  2. 在 try 代码中声明的资源被隐式声明为 final。
  3. 通过使用分号分隔每个声明可以管理多个资源。

格式:

try (创建流对象语句,如果多个可以使用';'隔开) {
    // dosomething
} catch (IOException e) {
    e.printStackTrace();
}

2️⃣JDK1.7 前

public static void writeFile(String str) {
    FileWriter fw = null;
    try {
        fw = new FileWriter("e://wg.txt", true);
        fw.write(str);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (fw != null) {
            try {
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3️⃣JDK1.7 后
资源关闭不需要写代码操作。这些可关闭的资源必须实现java.lang.AutoCloseable接口。比如将 FileWriter 放置 try() 中:

public static void writeFile(String str) {
    try (FileWriter fw = new FileWriter("e://wg.txt", true)) {
        fw.write(str);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

FileWriter 继承了 OutputStreamWriter。OutputStreamWriter 继承了 Writer。Writer 实现了 Closeable。Closeable 继承了 AutoCloseable。满足了带资源关闭的基本要求。当 try 中的{}执行完后,将会自动关闭资源。

4️⃣️理解

public class Demo {
    public static void main(String[] args) {
        try (MyResource resource = new MyResource();) {
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class MyResource implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("关闭自定义资源");
    }
}

结果如下:

关闭自定义资源

在 try () 中仅仅 new 了一个 MyResource 的对象,但 close() 中的输出语句执行了。看下反编译后的字节码:

class MyResource implements AutoCloseable {
    MyResource() {
    }
    public void close() throws Exception {
        System.out.println("关闭自定义资源");
    }
}

public class Demo {
    public Demo () {
    }
    public static void main(String[] args) {
        try {
            MyResource resource = new MyResource();
            resource.close();
        } catch (Exception var2) {
            var2.printStackTrace();
        }
    }
}

编译器竟然主动为 try-with-resources 进行了变身,在 try 中调用了 close()。在自定义类中再添加一个 out():

class MyResourceOut implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("关闭自定义资源");
    }
    public void out() throws Exception{
        System.out.println("hello,out");
    }
}

在 try{} 中调用一下 out():

public class DemoOut {
    public static void main(String[] args) {
        try (MyResourceOut resource = new MyResourceOut();) {
            resource.out();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

再来看一下反编译的字节码:

public class DemoOut {
    public DemoOut () {
    }

    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() 来获取这些异常。这样做的好处是不会丢失任何异常,方便调试。

PDDL入门 PDDL的组成部分 Objects:对象,世界上我们感兴趣的事物。 Predicates:谓词,我们感兴趣的事实(例如对象的属性),可以为真,也可以为假。 An initial state:初始化状态,我们开始所处的世界状态,即开始时为真的事物。 Goal specification:目标状态,我们想要结束的世界的状态,即我们希望最终成为真实的事情。 Actions/Operators:动作/操作,改变世界状态的方式,即发生的事情改变了事实。 PDDL语法 PDDL 文件的扩展名通常是.pddl 要 阅读详情

相关推荐

Win10 + Linux 双系统删除(Linux)

删除Linux所使用的磁盘分区 进入此电脑->计算机->管理->磁盘管理

weixin_52247624的博客 943

Use try-with-resources or close this “BufferedOutputStream“ in a “finally“ clause.

Sonar常见问题及修改建议(202001):https://blog.youkuaiyun.com/libusi001/article/details/103717457 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 一、报错信息 Use try-with-resources or close this "BufferedOutputStream"...

慕白Lee的博客 1万+

MATLAB联合Fluent优化仿真

matlab与fluent交互

keleke_的博客 4721

sonarQube扫描bug、漏洞处理汇总

目录 Bugs 漏洞 Bugs Use an "instanceof" comparison instead. Cast one of the operands of this integer division to a "double" Remove this throw statement from this finally block. 漏洞

liu_xue_xue的专栏 3万+

数字后端零基础入门系列 | Innovus零基础LAB学习Day9

数字后端零基础入门系列 | Innovus零基础LAB学习Day9

weixin_37584728的博客 4575

基于OSPF技术的某企业网络设计(完整文档+ENSP拓扑图)

主要对网络规划与设计,以企业网络为背景,对某个中型企业网络进行规划设计,该企业总部在南京,在常州有一个分公司,需要实现总部和分公司能够访问外网,能够让分公司内的用户或主机访问总部服务器的资源,并且保证数据的安全性。在这次总部企业网络设计中,考虑到资金的问题,核心层部署2台核心三层交换机,负责转发总部内部用户的流量,并充当内部用户网关,能够实现内部不同网段的用户之间的连通性。对于一些对网络比较敏感的企业或用户,对网络的要求较高,对于网络的稳定性和安全性也有较高的要求。

qq1325513482的博客 2万+

【sonar-block】Use try-with-resources or close this "BufferedInputStream" in a "finally" clause.

自己的理解: try-with-resources是JDK7的新语法结构,主要功能是自动关闭资源而不需要在finally里面手动close()关闭, 而且最重要的是,try块中的异常不会被close()引起的异常压制——因为不需要写close()了,系统自动帮你完成——前提是实现了AutoCloseable或Closeable接口的类或接口。 Throwable.getSuppressed方...

weixin_30654419的博客 2738

微信小程序实现锚点效果 scroll-view的scroll-into-view属性

小程序中实现锚点效果,可以直接使用scroll-view的scroll-into-view属性就可以实现锚点效果,比较方便简单。那么需要用到scroll-view那些参数呢,下面具体讲讲:效果展示: wxml **注意:**viewid值是动态的,通过setData设置即可。js wxss......

FaxMiao的博客 5447

sonar代码扫描bug:Use try-with-resources or close this "FileInputStream" in a "finally" clause.

下面代码 /** * 读取文件到byte数组 * * @param tradeFile * @return */ public static byte[] file2byte(File tradeFile) { try { FileInputStream fis = new FileInputStream(tradeFile); ByteAr...

gzyes 1724

iverilog+GTKwave使用总结

iverilog是一个开源的硬件描述语言(HDL)仿真工具,用于对硬件描述语言(如Verilog)编写的数字电路进行仿真。它可以将Verilog代码编译为仿真模型,并通过仿真运行来验证设计的正确性。iverilog支持IEEE 1364-2005 Verilog语言标准,并提供了丰富的功能,包括对多种Verilog语言特性的支持、模块化设计、测试平台等。它还可以与其他工具(如GTKWave波形查看器)配合使用,以便进行仿真后的波形查看和分析。

争取早日成为硅农 2万+

零基础入门simulink仿真--通信领域的调制解调技术:基于Simulink的PM信号调制与解调仿真建模示例

PM的基本原理是将基带信号(如语音或音乐信号)加载到高频载波信号的相位上。通过改变载波的瞬时相位,可以实现信息的传输。PM的优点包括抗噪声能力强、频谱利用率较高等,但其解调过程相对复杂。通过Simulink,我们可以通过模块化的建模方式实现PM信号的调制和解调过程,并观察信号在信道中的传输效果。通过本指南,我们介绍了如何基于Simulink搭建一个完整的PM信号调制与解调仿真模型,并进行仿真和性能评估。背景介绍:理解PM信号调制与解调的基本原理及其应用。所需工具和环境:列出进行PM仿真所需的工具和环境。

amy_mhd的博客 604

sonar静态扫描安全靶场webgoat

安装sonar并配置对webgoat进行sonar扫描扫描结果。

seanyang_的博客 3499

1.2 机器人控制系统软硬件平台

工业机器人的软硬件平台架构是影响工业机器人性能和效率的重要因素。良好的软硬件平台架构可以帮助工业机器人更加稳定和高效地完成工作,提高生产效率。正确的软硬件配置还可以提高工业机器人的灵活性和可靠性,使其能够更好地适应不断变化的生产环境。 同时,工业机器人的软硬件平台架构还可以影响工业机器人的安全性和维护成本。如果软硬件平台架构不合适,工业机器人可能出现故障或安全隐患,需要大量的维护和维修费用。因此,选择适当的软硬件平台架构对于确保工业机器人的高效运行和长期使用是非常重要的。

Galaxy_Robot的博客 2万+

try-with-resources 和 try-catch-finally的区别

是 Java 7 引入的语法糖,专门用于(如文件、流、数据库连接等),自动关闭资源,而是传统方式,需要手动关闭资源,容易出错。对比项是否自动关闭❌ 否✅ 是是否简洁❌ 冗长✅ 简洁是否安全⚠️ 容易出错✅ 安全可靠是否推荐❌ 不推荐(旧代码)✅强烈推荐💡结论:能用就不用来管理资源!如果你正在写文件操作、数据库连接、网络通信等代码,请务必使用。

qq_61723836的博客 686

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

try-with-resources和try-catch-finally的区别

1.try-with-resources 作用:捕捉异常,同时关闭资源。 使用条件: try-with-resources使用是java1.7增加了新特性,只要实现了AutoCloseable 或 Closeable,在try代码块结束之前,会自动关闭资源.。而字节输入流(InputStream),字节输出流(OutputStream),字符输入流(Reader),字符输出流(Writer)均实现...

日日留心的技术专栏 2291

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

try-catch-finally和try-with-resources

try-catch-finally语句的作用和示例。try-with-resources语句的作用和示例。

weixin_46485886的博客 498

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Java异常try-catch-finally和try-with-resources

Java 异常类层次结构图 在 Java 中,所有的异常都有一个共同的祖先 java.lang 包中的 Throwable 类。Throwable 类有两个重要的子类 Exception(异常)和 Error(错误)。Exception 能被程序本身处理(try-catch), Error 是无法处理的(只能尽量避免)。Exception 和 Error 二者都是 Java 异常处理的重要子类,各自都包含大量子类。 Exception :程序本身可以处理的异常,可以通过 catch 来进行捕获。Exce

qq_42390636的博客 788

try-with-resources优于try-catch-finally

在使用必须关闭的资源时,try-catch-finally是非常常用的选择,但是JDK7发布后,可以改变这种现状。 1. try-with-resources的使用 java中非常多的资源都继承了Closeable,例如FileInputStream了。在JDK1.7之后,继承了该接口的资源可以采取try-with-resources的方式关闭资源,因为该接口中有一个close方法,try-w...

sinat_36171694的博客 617

Java中的资源管理:try-with-resources vs try-catch-finally

Java提供了两种资源管理方式:传统的try-catch-finally和Java 7引入的try-with-resources。传统方式需要手动在finally块中关闭资源,代码冗长且容易出错。而try-with-resources自动管理实现了AutoCloseable接口的资源,语法更简洁,能自动处理异常和资源关闭,有效防止资源泄漏。虽然传统方式在特殊场景下仍有使用价值,但现代Java开发中推荐优先使用try-with-resources,它能显著提升代码的安全性和可维护性。这种语法尤其适用于文件I/

Knight 1144

try-catch-finally-return的执行顺序和try-with-resource语法糖

总结如下几条情况·try-catch-finally都有return语句时,没有异常时,返回值是finally中的return返回的·。try-catch都有return语句时,没有异常时,返回值是try中的return返回的try块中抛出异常,try、catch和finally中都有return语句,返回值是finally中的return。try块中抛出异常,try和catch中都有return语句,返回的catch中return值。

учёба 2095

Try-with-Resources[替代try-catch-finally的异常处理方式]

替代try-catch-finally的异常处理方式 实现Autocloseable接口 package cn.xxx.xxxx.utils; import java.io.Closeable; /** * @author hongliang.mei * @since 2020/4/2 15:22 */ public class MyResource implements AutoClo...

CsbLanca 749

Java进阶-try-with-resources

简单介绍了try-with-resources的使用

qq_44717657的博客 6212

用try-with-resources 代替try-catch-finally

面对必须要关闭的资源,我们总是应该优先使用 try-with-resources 而不是try-finally。随之产生的代码更简短,更清晰,产生的异常对我们也更有用。try-with-resources语句让我们更容易编写必须要关闭的资源的代码,若采用try-finally则几乎做不到这点。

DQ6667的博客 377

【Exception】如何使用 try-with-resources 优雅地关闭资源

一、背景         在 Java 编程中,如果打开了外部资源,如:文件输入输出流、数据库连接、网络连接(InputStream、OutputStream、java.sql.Connection)等,那我们必须在这些外部资源使用完后,去手动地关闭它们。因为外部资源不由JVM管理,无法享用JVM的垃圾回收机制。如果我们在编程时并没有确保在正确的时机关闭外部资源,就会导致外部资源泄露,就会出现文件被异常占用,数据库连接过多导致

sco5282的博客 1684

try-with-resources 代替 try - catch - finally

1、常规 try - catch - finally 写法 public String resdFile1(String filePath){ BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new FileReader(filePath)); return bufferedReader.readLine(); } catch (IOE

商亮的技术手册 723

关于try-catch-finally异常捕获,如何使用进阶版try-with-resources,finally语句的执行逻辑(面试常问:finally什么时候执行)

try、异常、try/catch/finally

zhangfuping123456789的博客 9470
上一篇: final、finally 和 finalize
下一篇: AOP理解及底层原理
JFS_Study
博客等级 码龄6年 363粉丝 359原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JFS_Study

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值