Java高效编程(9):优先使用 try-with-resources 而非 try-finally**

news2024/10/2 15:14:59

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界

在Java编程中,许多资源(如 InputStreamOutputStreamjava.sql.Connection)必须在使用后手动关闭。然而,开发者常常忘记关闭这些资源,导致严重的性能问题。虽然终结器(详见【条目8】)曾经被用作安全网,但它们并不可靠。在 Java 7 之前,try-finally 语句是确保资源正确关闭的唯一方式,即使在异常或提前返回时,try-finally 也能保证资源关闭:

// 使用 try-finally 关闭资源 - 不再是最佳方式
static String firstLineOfFile(String path) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        br.close();
    }
}

虽然这种方式看起来并不坏,但在处理多个资源时,它会变得非常繁琐:

// 使用 try-finally 处理多个资源时代码显得复杂
static void copy(String src, String dst) throws IOException {
    InputStream in = new FileInputStream(src);
    try {
        OutputStream out = new FileOutputStream(dst);
        try {
            byte[] buf = new byte[BUFFER_SIZE];
            int n;
            while ((n = in.read(buf)) >= 0) {
                out.write(buf, 0, n);
            }
        } finally {
            out.close();
        }
    } finally {
        in.close();
    }
}

即使是优秀的程序员,也经常在 try-finally 中犯错。事实上,Java 库中有三分之二的 close 方法调用在2007年是错误的。

使用 try-finally 的问题

即使 try-finally 可以正确关闭资源,但它存在一个微妙的问题:try 块和 finally 块中的代码都可能抛出异常。例如,在 firstLineOfFile 方法中,readLine 方法可能由于设备故障抛出异常,而 close 方法也可能因此失败。在这种情况下,后续的异常会掩盖第一个异常,导致调试变得非常困难。虽然可以编写代码来抑制第二个异常,但几乎没有人会这么做,因为代码会变得冗长复杂。

Java 7 的解决方案:try-with-resources

Java 7 引入了 try-with-resources 语句,解决了 try-finally 的所有问题。要使用该语句,资源类必须实现 AutoCloseable 接口,该接口只有一个返回 voidclose 方法。Java 库和第三方库中的许多类现在都实现了该接口。以下是使用 try-with-resources 重写的 firstLineOfFile 方法:

// 使用 try-with-resources - 最佳资源关闭方式
static String firstLineOfFile(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

try-with-resources 同时处理多个资源时,代码更加简洁:

// 使用 try-with-resources 处理多个资源 - 简洁明了
static void copy(String src, String dst) throws IOException {
    try (InputStream in = new FileInputStream(src);
         OutputStream out = new FileOutputStream(dst)) {
        byte[] buf = new byte[BUFFER_SIZE];
        int n;
        while ((n = in.read(buf)) >= 0) {
            out.write(buf, 0, n);
        }
    }
}

try-with-resources 的优势

try-finally 相比,try-with-resources 更加简洁且易于维护。它不仅减少了冗余的代码,还提供了更好的异常处理机制。如果在 try 块和 close 方法中同时抛出异常,try-with-resources 会抑制后续异常,并保留最重要的第一个异常。抑制的异常不会被简单忽略,而是记录在异常堆栈中,并带有“抑制异常”的说明。你可以通过 Throwable.getSuppressed 方法程序化地访问这些抑制的异常。

你也可以像在普通 try-finally 中一样,为 try-with-resources 添加 catch 子句来处理异常。如下所示是一个不抛出异常的 firstLineOfFile 版本,它在无法打开文件时返回默认值:

// 带有 catch 子句的 try-with-resources
static String firstLineOfFile(String path, String defaultVal) {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    } catch (IOException e) {
        return defaultVal;
    }
}

通过这种方式,你可以优雅地处理异常,而无需增加代码的嵌套层次。

总结

try-with-resources 是关闭资源的最佳方式。它不仅代码简洁、清晰,而且能够正确处理多个异常,确保抛出的异常是最有用的,抑制的异常也不会丢失。与 try-finally 相比,try-with-resources 的优势明显,强烈建议在需要关闭资源的场景下使用这一语句。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2184611.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【STM32-HAL库】自发电型风速传感器(使用STM32F407ZGT6)(附带工程下载链接)

一、自发电型风速传感器介绍 自发电型风速传感器,也称为风力发电型风速传感器或无源风速传感器,是一种不需要外部电源即可工作的风速测量设备。这种传感器通常利用风力来驱动内部的发电机构,从而产生电能来供电测量风速的传感器部分。以下是自…

从u盘直接删除的文件能找回吗 U盘文件误删除如何恢复

U盘上的文件被删除并不意味着它们立即消失。事实上,删除操作只是将文件从文件系统的目录中移除,并标记可用空间。这意味着在文件被覆盖之前,它们仍然存在于存储介质上。因此,只要文件没有被新的数据覆盖,我们就有机会恢…

一本应用《软件方法》的书《软件需求分析和设计实践指南》

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 昨天看到了韩雪燕、李楠等老师写的《软件需求分析和设计实践指南》,前言提到了我。特别说明的是,这个书我自己看到的,韩老师等之前也未和我提过--这…

电子采购招投标比价供应商在线询价定标审批管理系统(源码)

前言: 随着互联网和数字技术的不断发展,企业采购管理逐渐走向数字化和智能化。数字化采购平台作为企业采购管理的新模式,能够提高采购效率、降低采购成本、优化供应商合作效率,已成为企业实现效益提升的关键手段。系统获取在文末…

前端组件化开发

假设这个页面是vue开发的,如果一整个页面都是编写在一个vue文件里面,后期不好维护,会特别的庞大,那么如何这个时候需要进行组件化开发。组件化开发后必然会带来一个问题需要进行组件之间的通信。组要是父子组件之间通信&#xff0…

[Linux]从零开始的网站搭建教程

一、谁适合本次教程 学习Linux已经有一阵子了,相信大家对LInux都有一定的认识。本次教程会教大家如何在Linux中搭建一个自己的网站并且实现内网访问。这里我们会演示在Windows中和在Linux中如何搭建自己的网站。当然,如果你没有Linux的基础,这…

【一篇文章理解Java中多级缓存的设计与实现】

文章目录 一.什么是多级缓存?1.本地缓存2.远程缓存3.缓存层级4.加载策略 二.适合/不适合的业务场景1.适合的业务场景2.不适合的业务场景 三.Redis与Caffine的对比1. 序列化2. 进程关系 四.各本地缓存性能测试对比报告(官方)五.本地缓存Caffine如何使用1. 引入maven依…

陶瓷4D打印有挑战,水凝胶助力新突破,复杂结构轻松造

大家好!今天要和大家聊聊一项超酷的技术突破——《Direct 4D printing of ceramics driven by hydrogel dehydration》发表于《Nature Communications》。我们都知道4D打印很神奇,能让物体随环境变化而改变形状。但陶瓷因为太脆太硬,4D打印一…

java中创建不可变集合

一.应用场景 二.创建不可变集合的书写格式(List,Set,Map) List集合 package com.njau.d9_immutable;import java.util.Iterator; import java.util.List;/*** 创建不可变集合:List.of()方法* "张三","李四","王五…

鸿蒙开发选择表情

鸿蒙开发选择表情 动态评论和聊天信息都需要用到表情,鸿蒙是没有提供的,得自己做 一、思路: 用表情字符显示表情,类似0x1F600代表笑脸 二、效果图: 三、关键代码: // 联系:893151960 Colum…

蓝桥杯【物联网】零基础到国奖之路:十五. 扩展模块之双路ADC

蓝桥杯【物联网】零基础到国奖之路:十五. 扩展模块之双路ADC 第一节 硬件解读第二节 CubeMX配置第三节 代码编写 第一节 硬件解读 STM32的ADC是12位,通过硬件过采样扩展到16位,模数转换器嵌入到STM32L071xx器件中。有16个外部通道和2个内部通道&#xf…

PDF阅读器工具集萃:满足你的多样需求

现在阅读书籍大部分都喜欢电子书的形式了吧,因为小小的一个设备就能存下上万本书。从流传程度来说PDF无疑是一个使用最广的格式。除了福昕PDF阅读器阅读之外还有哪些好用的阅读工具呢/?今天我们一起来探讨一下吧。 1.福昕阅读器 链接一下>>www.f…

css3-----2D转换、动画

2D 转换(transform) 转换(transform)是CSS3中具有颠覆性的特征之一,可以实现元素的位移、旋转、缩放等效果 移动:translate旋转:rotate缩放:scale 二维坐标系 2D 转换之移动 trans…

SysML案例-清朝、火星人入侵地球

DDD领域驱动设计批评文集>> 《软件方法》强化自测题集>> 《软件方法》各章合集>> 以下图形摘自Jon Holt和Simon Perry的SysML for Systems Engineering。 案例素材来自H. G. Wells在1898年(没错,清朝)出版的The War of…

Netty系列-7 Netty编解码器

背景 netty框架中,自定义解码器的起点是ByteBuf类型的消息, 自定义编码器的终点是ByteBuf类型。 1.解码器 业务解码器的起点是ByteBuf类型 netty中可以通过继承MessageToMessageEncoder类自定义解码器类。MessageToMessageEncoder继承自ChannelInboundHandlerAdap…

用于高频交易预测的最优输出LSTM

用于高频交易预测的最优输出LSTM J.P.Morgan的python教程 Content 本文提出了一种改进的长短期记忆(LSTM)单元,称为最优输出LSTM(OPTM-LSTM),用于实时选择最佳门或状态作为最终输出。这种单元采用浅层拓…

CSS 盒子属性

1. 盒子模型组成 1.1 边框属性 1.1.1 四边分开写 1.1.2 合并线框 1.1.3 边框影响盒子大小 1.2 内边距 注意: 1.3 外边距 1.3.1 嵌套块元素垂直外边距的塌陷 1.4 清除内外边距 1.5 总结

使用YOLO11训练自己的数据集【下载模型】-【导入数据集】-【训练模型】-【评估模型】-【导出模型】

目录 前言:一、下载模型二、导入数据集三、训练自己的数据集四、验证数据集五、测试数据集 前言: YOLO11于2024年9月30日由YOLOv8团队正式发布,为了让我们能够趁热打铁早发论文,接下来让我们仔细研究一下如何使用YOLO11训练自己的…

通信协议感悟

本文结合个人所学,简要讲述SPI,I2C,UART通信的特点,限制。 1.同步通信 UART,SPI,I2C三种串行通讯方式,SPI功能引脚为CS,CLK,MOSI,MISO;I2C功能引…

六、输入输出管理

1.输入输出程序接口 由于各种设备的操作所提供的参数或者返回值都不同,也很难做到以设备独立性软件向上提供统一的接口,但是可以将设备进行分类,每一类设备由一种统一的接口操作。 ①字符设备接口 get/put 系统调用:向字符设备读/写一个字符…