首页 > 其他分享 >自动调用关闭释放资源try-with-resource

自动调用关闭释放资源try-with-resource

时间:2024-07-22 11:07:52浏览次数:8  
标签:调用 resource 字节 writer try FileWriter close

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

有哪些使用姿势

  1. 基本使用方法,只需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");
        }
    
  2. 可以结合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方法。

标签:调用,resource,字节,writer,try,FileWriter,close
From: https://www.cnblogs.com/Nuwa/p/18315653

相关文章

  • vue非常常用的页面传参、调用(一定要牢牢记住!)
    一.首先,是最基础的在父组件中引入子组件,调用子组件,如下:   1.引入组件   2.注册组件   3.调用组件  父组件parent.vue ↓   子组件child.vue ↓二.然后,我们来学习父组件传递参数给子组件,如下:   1.父组件其实是用v-bind属......
  • Robot Framework 数据库库调用 Oracle 存储过程失败,并出现字符到数字转换错误
    我有一个OraclePL/SQL程序,我可以直接调用如下,没有问题:BEGINexample_package_name.example_procedure(p_item_no=>123456,p_send_now=>true);END;(注意:p_item_no期望aNUMBER和p_send_now期望aBOOLEAN)我正在......
  • 智普ai的并发调用-----go编写
    //https://github.com/zhangbo2008/Concurrency_zhipuAI_callpackagemainimport( "bytes" "encoding/json" "fmt" "io" "net/http" "sync" "time")varzhipuapikey="xxxxxxxxxx......
  • 超好用!空号检测接口使用与调用示例
    空号检测接口是通过调用第三方提供的API接口,实现对手机号码是否为空号的检测服务。它可以帮助快速、准确地识别出无效号码,避免无效的通信,提高通信效率,适用于短信群发、电话营销、注册验证等场景。一、在选择空号检测接口时,你可以考虑以下因素:1.数据准确性:确保接口提供的检......
  • Spring Resources 入门
    1.介绍Resources是Spring框架中的一个核心模块,用于处理资源文件的访问。它提供了一种方便的方式来访问不同类型的资源,如文件、类路径下的资源、网络上的资源等。Spring提供了统一的资源访问机制,使得开发者可以更加方便地操作各种资源。接下来让我们来学习关于Resource......
  • 如何在 python 脚本中调用 robocopy 来批量复制多个文件夹?
    我正在尝试在网络驱动器之间移动多个大文件夹(>10Gb、>100个子文件夹、>2000个文件)。我尝试过在python中使用Shutil.copytree命令,它工作得很好,只是由于不同的原因它无法复制一小部分(<1%的文件)。我相信robocopy对我来说是最好的选择,因为我可以创建一个记录传输过......
  • 【微服务】第38节:微服务的OpenFeign远程调用
    1.远程调用我们知道微服务间远程调用都是有OpenFeign帮我们完成的,甚至帮我们实现了服务列表之间的负载均衡。但具体负载均衡的规则是什么呢?何时做的负载均衡呢?接下来我们一起来分析一下。1.1.负载均衡原理在SpringCloud的早期版本中,负载均衡都是有Netflix公司开源的Ribbon......
  • 易优CMS按年月日来调用文章排行函数
    网站根目录extend/function.php“文件内写入if(!function_exists('diy_archives_list')){//获取指定天数的文档列表functiondiy_archives_list($channel=0,$day=0,$orderby='aid',$limit=10){$where=[];!empty($channel)&&$......
  • 顺丰快递查询|阿里云调用API接口实现
    介绍:本次解析通过阿里云云市场的云服务来实现程序中对快递包裹实时监控,首先需要准备选择一家可以提供快递查询的商品。https://market.aliyun.com/apimarket/detail/cmapi00065859#sku=yuncode5985900001步骤1:选择商品如图点击免费试用,即可免费申请该接口数据。步骤......
  • 记一个引起MYSQL死锁Deadlock found when trying to get lock; try restarting transac
    一、记一个引起MYSQL死锁Deadlockfoundwhentryingtogetlock;tryrestartingtransaction的例子  今天在尝试MYSQL事务的时候,这种情况总会引起死锁,不知道为什么,我使用的测试MYSQL表的创建SQL如下:CREATETABLE`user`(`id`int(10)unsignedNOTNULLAUTO_INC......