首页 > 编程语言 >Java 中的 try-with-resources 详解

Java 中的 try-with-resources 详解

时间:2024-11-07 08:47:38浏览次数:3  
标签:Java try new catch close public resources

在 Java 7 之前,处理资源关闭通常使用 try-catch-finally 块。虽然这种方式可以确保资源被正确关闭,但代码显得冗长且容易出错。Java 7 引入了 try-with-resources 语法,使得资源管理变得更加简洁和安全。本文将详细介绍 try-with-resources 的使用方法和优势。

1 try-catch-finally 的回顾

在介绍 try-with-resources 之前,我们先回顾一下传统的 try-catch-finally 块的使用方法。

示例:

public class TrycatchfinallyDecoder {
    public static void main(String[] args) {
        BufferedReader br = null;
        try {
            String path = TrycatchfinallyDecoder.class.getResource("/牛逼.txt").getFile();
            String decodePath = URLDecoder.decode(path, "utf-8");
            br = new BufferedReader(new FileReader(decodePath));

            String str = null;
            while ((str = br.readLine()) != null) {
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这个例子中,我们使用 try-catch-finally 块来读取文件内容并确保 BufferedReader 资源被正确关闭。虽然这种方式可以确保资源被关闭,但代码显得冗长且容易出错,尤其是在 finally 块中还需要处理 close() 方法可能抛出的异常。

2 try-with-resources 的引入

try-with-resources 语法简化了资源管理,使得代码更加简洁和安全。要使用 try-with-resources,资源必须实现 AutoCloseable 接口。

示例:

try (BufferedReader br = new BufferedReader(new FileReader(decodePath))) {
    String str = null;
    while ((str = br.readLine()) != null) {
        System.out.println(str);
    }
} catch (IOException e) {
    e.printStackTrace();
}

在这个例子中,BufferedReader 资源在 try 块结束后会自动关闭,无需显式调用 close() 方法。

3 多个资源的管理

try-with-resources 语法支持同时管理多个资源,只需在 try 后的括号中声明多个资源即可。

示例:

try (BufferedReader br = new BufferedReader(new FileReader(decodePath));
     PrintWriter writer = new PrintWriter(new File(writePath))) {
    String str = null;
    while ((str = br.readLine()) != null) {
        writer.print(str);
    }
} catch (IOException e) {
    e.printStackTrace();
}

在这个例子中,BufferedReaderPrintWriter 资源都会在 try 块结束后自动关闭。

4 自定义资源的管理

如果需要管理自定义资源,只需让资源类实现 AutoCloseable 接口,并提供 close() 方法。

示例:

public class TrywithresourcesCustom {
    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("关闭自定义资源");
    }
}

在这个例子中,MyResource 类实现了 AutoCloseable 接口,并在 close() 方法中执行资源关闭操作。在 try-with-resources 块中使用 MyResource 对象时,close() 方法会自动调用。

反编译后的字节码:

class MyResource implements AutoCloseable {
    MyResource() {
    }

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

public class TrywithresourcesCustom {
    public TrywithresourcesCustom() {
    }

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

    }
}

编译器主动为try-with-resources进行了变身,在 try 中调用了 close() 方法。

5 异常处理

try-with-resources 语法在处理异常时更加优雅。如果 try 块中的代码和资源关闭时都抛出异常,try-with-resources 会自动处理这些异常,并将被抑制的异常附加到主异常中。

示例:

class MyResourceOutThrow implements AutoCloseable {
    @Override
    public void close() throws Exception {
        throw new Exception("close()");
    }

    public void out() throws Exception {
        throw new Exception("out()");
    }
}

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

运行结果:

java.lang.Exception: out()
    at com.cmower.dzone.trycatchfinally.MyResourceOutThrow.out(TrywithresourcesCustomOutThrow.java:20)
    at com.cmower.dzone.trycatchfinally.TrywithresourcesCustomOutThrow.main(TrywithresourcesCustomOutThrow.java:6)
    Suppressed: java.lang.Exception: close()
        at com.cmower.dzone.trycatchfinally.MyResourceOutThrow.close(TrywithresourcesCustomOutThrow.java:16)
        at com.cmower.dzone.trycatchfinally.TrywithresourcesCustomOutThrow.main(TrywithresourcesCustomOutThrow.java:5)

在这个例子中,out() 方法和 close() 方法都抛出了异常。try-with-resources 语法将 close() 方法的异常附加到 out() 方法的异常中,并使用 Suppressed 关键字标记,使得调试更加方便。

反编译后的字节码:

public class TrywithresourcesCustomOut {
    public TrywithresourcesCustomOut() {
    }

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

6 思维导图

在这里插入图片描述

7 参考链接

深入理解 Java 中的 try with resources

标签:Java,try,new,catch,close,public,resources
From: https://blog.csdn.net/gaosw0521/article/details/143503940

相关文章

  • JavasScript 的对象事件的处理程序
    1、鼠标事件常用的鼠标事件有MouseDown、MouseUp、MouseMove、MouseOver、MouseOut、Click、Blur及Focus等事件。mousedown:按下鼠标键时触发 mouseup:抬起鼠标键时触发 click:单击鼠标时触发 dblclick:在同一个元素上双击鼠标时触发 mouseenter:鼠标进入一个节点时触发,进......
  • 数组的介绍--Java
    1、数组是什么    数组就是一个容器,里面存放的是一组同种类型的数据。    Example:    1,3,5,7,8,10,12    int[]arr={1,3,5,7,8,10,12};    //  该数组存放的都是整型数据    李白,后羿,诸葛亮,刘邦,庄周    ......
  • javascript函数
    1.1初识函数1.1.1函数的定义1.函数用于封装一段特定功能的代码作用:提高代码的复用性,降低维护的难度(你将实现一个功能多段重复的代码变为一段代码,降低了维护的难度,你将这段代码用一个函数封装,要使用这个功能的时候就调用函数,即可提高代码的复用性)1.1.2函数的定义与使用1.函......
  • Java初学者指南
    Java是什么?Java是一种高级、面向对象的编程语言,设计目的是平台无关性,允许开发者“一次编写,到处运行”(WORA)。这意味着Java代码在一个平台上编译后,可以在任何支持Java的平台上运行,而无需重新编译。Java的历史由詹姆斯·高斯林和SunMicrosystems于1991年发明。......
  • 2025最新-计算机毕业设计java基于Springboot的智慧教学平台的系统设计与实现
    一、项目介绍  基于SpringBoot的智慧教学平台系统设计与实现是一个复杂但充满挑战的项目,旨在通过现代软件开发技术优化教育流程,提升教学质量和管理效率。以下是对该系统的详细介绍:智慧教学平台是一款集成了多种功能的综合性教育管理系统,通过运用SpringBoot框架、MySQ......
  • javascript模块 (Module) 简介
    https://blog.csdn.net/chehec2010/article/details/119804381   随着ES6的出现,js模块已经成为正式的标准了。曾经为了解决js模块问题而发展起来的民间秘籍,requireJs(AMD)、SeaJs(CMD)、Node(CommonJs),已经或者不久的将来会成为历史。了解历史也是很重要的,因为正式标准就是......
  • 基于Java+SpringBoot心理测评心理测试系统功能实现三
    一、前言介绍:1.1项目摘要心理测评和心理测试系统在当代社会中扮演着越来越重要的角色。随着心理健康问题日益受到重视,心理测评和心理测试系统作为评估个体心理状态、诊断心理问题、制定心理治疗方案的工具,其需求和应用范围不断扩大。首先,现代社会节奏快速,竞争激烈,人们面临着来......
  • 基于Java+SpringBoot心理测评心理测试系统功能实现四
    一、前言介绍:1.1项目摘要心理测评和心理测试系统在当代社会中扮演着越来越重要的角色。随着心理健康问题日益受到重视,心理测评和心理测试系统作为评估个体心理状态、诊断心理问题、制定心理治疗方案的工具,其需求和应用范围不断扩大。首先,现代社会节奏快速,竞争激烈,人们面临着来......
  • Redis4:Redis的Java客户端
    欢迎来到“雪碧聊技术”CSDN博客!在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将不断探索Java的深邃世界,分享最新的技术动态、实战经验以及项目......
  • Java中数组“扩容”
    数组一旦创建是不能改变大小的!!!!!此处的数组"扩容"是看起来的像扩容的一种使用方式而已,不是真的改变数组大小.....可以实现,让数组用的时候感觉变大了....思路:其实创建了一个更大的数组,然后将之前数组元素拷贝大数组中,然后将大数组返回给你用。publicstaticvoidmai......