首页 > 其他分享 >开关资源新方法:Try- with-resources

开关资源新方法:Try- with-resources

时间:2024-08-14 13:37:42浏览次数:9  
标签:try myresources1 Try 开关 resources 关闭 new 资源

JDK7新特性:Try- with-resources

try-with-resources 是 JDK 7中引入的一种新的异常处理机制,它主要用于自动管理资源,能够很容易地关闭在 try-catch 语句块中使用的资源。确保资源在不再需要时能够被正确关闭。这种机制简化了资源管理,使得资源的释放更加安全和可预测。

resource:是指在程序完成后,必须关闭的对象(例如:文件资源File、IO流、Socket、ServerSocket网络对象、数据库链接对象等)。try-with-resources 语句确保了每个资源在语句结束时关闭。

普通开关资源方法

class Myresources1 implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("资源1关闭方法执行");
        throw new Exception("资源1关闭异常");
    }
}
class Myresources2 implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("资源2关闭方法执行");
        throw new Exception("资源2关闭异常");
    }
}

为了避免在代码执行中出现异常,使用try-catch-finally进行异常捕获

        Myresources1 myresources1 =null;
        Myresources2 myresources2 = null;
        try{
            myresources1 = new Myresources1();
            myresources2 = new Myresources2();
            System.out.println("hello");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (myresources1!=null){
                try {
                    myresources1.close();
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    if (myresources2!=null){
                        try {
                            myresources2.close();
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

image.png

Try- with-resources控制资源语法:

    try(Myresources1 myresources1 = new Myresources1();
        Myresources2 myresources2 = new Myresources2();){
           System.out.println("hello");
        //int a = 2/0;
       }catch (Exception e){
           e.printStackTrace();
       }

try-with-resource中声明的变量会隐式的加上final 关键字,所以无法再进行赋值image.png

处理规则

  • 凡是实现了AutoCloseable或者Closeable接口的类,在try()里声明该类实例的时候,在try结束后,close方法都会被调用。不管是否出现异常(int i=1/0会抛出异常),try()里的实例都会被调用close方法

image.png![imag

e.png](https://cdn.nlark.com/yuque/0/2024/png/42425790/1722909280844-945838ee-91a2-4a06-9399-647b744396f1.png#averageHue=%231f2125&clientId=ua8faed9b-5ab9-4&from=paste&height=259&id=TKIhf&originHeight=259&originWidth=735&originalType=binary&ratio=1&rotation=0&showTitle=false&size=37054&status=done&style=none&taskId=u35bf969c-e938-4d98-ab98-4df1f077383&title=&width=735)

image.png

  • 越晚声明的对象,会越早被close掉。
  • try结束后自动调用的close方法,这个动作会早于finally里调用的方法。

image.pngimage.png

异常抑制问题

Myresources1 myresources1 = null;
        try{
            myresources1 = new Myresources1();
            //算数异常
            System.out.println(10/0);
        }finally {
            if (myresources1!=null)
                myresources1.close();
        }

//myresources1类
class Myresources1 implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("资源1关闭方法执行");
        throw new Exception("资源1关闭异常");
    }
}

运行异常打印:

image.png
此时可以看到,异常只打印了close()方法的异常,而 10/0 的异常被抑制了

        try(Myresources1 myresources1 = new Myresources1();){
            System.out.println(10/0);
        }

运行异常打印:image.png<br 当一个异常被抛出的时候,可能有其他异常因为该异常而被抑制住,从而无法正常抛出。这时可以通过addSuppressed() 方法把这些被抑制的方法记录下来,然后被抑制的异常就会出现在抛出的异常的堆栈信息中,可以通过 getSuppressed() 方法来获取这些异常。这样做的好处是不会丢失任何异常,方便我们进行调试。

反编译代码:

image.png

        Myresources1 myresources1 = new Myresources1();
        Throwable var2 = null;

        try {
            System.out.println(10 / 0);
        } catch (Throwable var11) {
            var2 = var11;
            throw var11;
        } finally {
            if (myresources1 != null) {
                //判断程序运行时是否出现异常
                if (var2 != null) {	//出现异常
                    try {
                        myresources1.close();
                    } catch (Throwable var10) {
                        var2.addSuppressed(var10);	//把close()发生的异常添加为抑制异常
                    }
                } else {	//程序运行时无异常
                    myresources1.close();
                }
            }

        }

循环打印抑制异常

 try(Myresources1 myresources1 = new Myresources1();){
​            System.out.println(10/0);
​        }catch (Exception e){
​            e.printStackTrace();
​            Throwable[] suppressed = e.getSuppressed();
​            for (Throwable t : suppressed){
​                t.printStackTrace();
​            }
​        }

运行结果:

image.png

使用场景

try-with-resources 语法适用于任何需要自动管理资源关闭,以防止资源泄漏的场景。

简单粗暴点就是,ctrl点进去看当前资源,只要当前资源实现了AutoCloseable或者Closeable接口就可以用。但是,具体使用还要根据要实现的业务场景来决定。

不适合的场景:

  1. 资源未实现AutoCloseable或Closeable接口:

如果资源没有实现 AutoCloseableCloseable 接口,那么它就不能在 try-with-resources 语句中被自动关闭。这种情况下,仍然需要手动关闭资源,或者使用其他机制来确保资源的正确关闭。

  1. 资源需要在try块外部使用:

try-with-resources 语句中的资源在 try块执行完毕后会自动关闭,因此在 try块外部无法访问这些资源。如果资源需要在 try 块外部被使用,那么就不能使用 try-with-resources语句来管理这些资源。

  1. 需要精细控制资源关闭时机:

在某些情况下,开发者可能需要根据特定的逻辑或条件来决定何时关闭资源,而不是在 try 块结束时立即关闭。try-with-resources 语句无法提供这种精细的控制,因此在这些场景下可能不适用。

  1. 资源关闭可能抛出异常且需要特殊处理:

虽然 try-with-resources 语句会尝试关闭资源,并捕获在关闭过程中抛出的异常,但这些异常通常会被抑制(suppressed),而不是直接抛出。如果开发者需要特别处理这些关闭异常,或者需要将这些异常与 try 块中抛出的其他异常进行区分,那么 try-with-resources 可能不是最佳选择。

  1. 资源需要在多个try块中共享:

如果一个资源需要在多个 try块中被共享和使用,那么使用 try-with-resources 语句可能会变得复杂或不可行。因为每个 try-with-resources 语句都会尝试在结束时关闭其声明的资源,这可能会导致资源在需要时已经被关闭。

  1. 资源关闭逻辑复杂:

如果资源的关闭逻辑非常复杂,或者需要在关闭前执行一些特定的操作(如回滚事务、释放锁等),那么使用 try-with-resources语句可能不足以满足需求。在这些情况下可能需要编写更复杂的finally块来确保资源的正确关闭。综上所述,try-with-resources 语句虽然是一种强大的资源管理机制,但它并不适用于所有场景。在选择是否使用 try-with-resources 时,开发者需要根据具体的需求和资源的特点来做出决策。

优点:

  1. 简化资源管理代码:无需显式地在 finally 块中编写资源关闭的代码,减少了代码量和出错的可能性。
  2. 提高代码可读性:使资源的管理更加清晰和直观,让开发者能够更专注于业务逻辑。
  3. 确保资源及时关闭:即使在 try 块中发生异常,资源也会被自动关闭,避免了资源泄漏的风险。
  4. 支持多个资源:可以同时管理多个资源,它们都会按照声明的反顺序被正确关闭。

缺点:

  1. 支持的资源类型有限:并非所有的类都可以作为 try-with-resources 的资源,只有实现了 AutoCloseableCloseable 接口的类才行。

  2. 性能考虑:

    虽然try-with-resources在大多数情况下对性能的影响可以忽略不计,但在极端情况下(例如:在性能敏感的应用程序中频繁地打开和关闭大量资源),它可能会引入一些额外的开销。这是因为 try-with-resources语句在编译时会生成额外的代码来管理资源的关闭。

  3. 对在 try() 中声明的对象不能重新赋值

     FileWriter fw = new FileWriter("a.txt");
     fw = new FileWriter("e:/b.txt");
		try(FileWriter fw = new FileWriter("a.txt")){
            fw = new FileWriter("b.txt");	//报错
        }catch (Exception e){
            e.printStackTrace();
        }

//此时会编译出错:The resource is1 of a try-with-resources statement cannot be assigned

官方文档:
It is a compile-time error if final appears more than once as a modifier for each variable declared in a resource specification.
A variable declared in a resource specification is implicitly declared final (§4.12.4) if it is not explicitly declared final.
在资源规范中声明的每个变量,如果 final 作为修饰符出现不止一次,则属于编译时错误。
在资源规范中声明的变量,如果没有显式地声明为 final,则隐式地声明为 final(§4.12.4)。

try-with-resource中声明的变量会隐式的加上final 关键字,所以无法再进行赋值


总结:

try-with-resources 的优点通常大于缺点,在大多数情况下,它是一种更安全、简洁和可靠的资源管理方式。具体的使用方式根据业务场景决定,但是一般情况下,处理必须关闭的资源时,始终有限考虑使用 try-with-resources,而不是 try–catch-finally。前者产生的代码更加简洁、清晰,产生的异常信息也更靠谱。

标签:try,myresources1,Try,开关,resources,关闭,new,资源
From: https://www.cnblogs.com/tongluoshao/p/18358601

相关文章

  • [Paper Reading] Multiple View Geometry Transformers for 3D Human Pose Estimation
    MultipleViewGeometryTransformersfor3DHumanPoseEstimationlink时间:CVPR2024机构:UniversityofToronto&&SoutheastUniversity&&MicrosoftResearchAsiaTL;DR提出一种基于Transformer端到端3DHumanPoseEstimation方法MVGFormer,核心模块是geometry与appea......
  • npm报错:request to https://registry.npm.taobao.org failed处理办法
    今天在安装flowise的时候提示npm报错:requestto https://registry.npm.taobao.org failed,reasoncertificatehasexpired看提示是淘宝镜像过期了。找了一下资料,好像是npm淘宝镜像已经从 registry.npm.taobao.org 切换到了 registry.npmmirror.com。旧域名也将于2022......
  • Opentelemetry collector用法
    Opentelemetrycollector用法目录Opentelemetrycollector用法ServiceExtensionshealthcheckextensionPipelinesreceiverOTLPReceiverprometheusreceiverfilelogreceiverProcessor数据归属Importantmemorylimiterprocessorbatchprocessorattributesprocessor&&Resourc......
  • switch和try-catch综合练习
    //输入任意年份,月份,判断该月份天数;staticvoidMain(string[]args){intintDay=0;intintYear=0;intintMonth=0;//任意输入年份和月份,判断该月有几天;try......
  • 洛谷 P3870 开关之线段树板子
    洛谷P3870题解传送锚点摸鱼环节[TJOI2009]开关题目描述现有\(n\)盏灯排成一排,从左到右依次编号为:\(1\),\(2\),……,\(n\)。然后依次执行\(m\)项操作。操作分为两种:指定一个区间\([a,b]\),然后改变编号在这个区间内的灯的状态(把开着的灯关上,关着的灯打开);指定一个区间......
  • 开关电源设计学习笔记
    在学习开关电源设计之前,我们应该思考一下学习的初心和目标,初心是能在你想要放弃的时候坚持下去的动力,目标是怎样才能算完成了对于硬件的认识和学习,是对于学习成果的检验。我们所学的知识想要转化为技能和能力都需要在实践中进行的,所以,在学习中我们的目标设立在运用所学知识设......
  • Python 依赖管理神器 Poetry 深入指南
    Poetry依赖管理详细教程引言在现代软件开发中,依赖管理是项目成功的关键。Python开发者现在有了一个新的选择:Poetry。Poetry是一个现代的Python包管理工具,旨在简化Python项目的创建、打包和发布。它提供了一种更直观和高效的方式来管理项目的依赖关系,相较于传统的p......
  • MMBT3906-ASEMI低压PNP开关三极管MMBT3906
    编辑:llMMBT3906-ASEMI低压PNP开关三极管MMBT3906型号:MMBT3906品牌:ASEMI批号:2024+封装:SOT-23三极管类型:PNP集电极电流(Ic):200mA集射极击穿电压(Vceo):40V安装方式:表贴式封装特性:NPN晶体管、三极管、40V硅晶体管产品引线数量:3产品内部芯片个数:1产品内部芯片尺寸:MIL工作......
  • 手机充电器和电脑开关电源引起跳闸
    存在场景(总空开跳闸):办公区,每人一套PC电脑(开关电源)+一个手机充电器(原理也是开关电源),停电后,突然恢复供电,启动瞬间电流远远大于额定值,引起总开关跳闸。浪涌电流产生原因PC电脑为开关电源,开关电源一般都采用整流滤波的原理,在开关电源启动的瞬间,大电容首先充电,在启动瞬间......
  • 解决Python的pip问题:WARNING: Retrying (Retry(total=1, connect=None, read=None, re
    相关:pip安装第三方库报错Retrying(Retry(total=1,connect=None,read=None,redirect=None,status=None))国内镜像源下载常用国内源:清华:https://pypi.tuna.tsinghua.edu.cn/simple/阿里云:http://mirrors.aliyun.com/pypi/simple/中国科技大学https://pypi.mirrors.u......