Tips

《Effective Java, Third Edition》一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化。

在这里第一时间翻译成中文版。供大家学习分享之用。

9. 使用try-with-resources语句替代try-finally语句

Java类库中包含许多必须通过调用close方法手动关闭的资源。 比如InputStreamOutputStreamjava.sql.Connection。 客户经常忽视关闭资源,其性能结果可想而知。 尽管这些资源中有很多使用finalizer机制作为安全网,但finalizer机制却不能很好地工作(条目 8)。

从以往来看,try-finally语句是保证资源正确关闭的最佳方式,即使是在程序抛出异常或返回的情况下:

// try-finally - No longer the best way to close resources!
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
}

这可能看起来并不坏,但是当添加第二个资源时,情况会变得更糟:

// try-finally is ugly when used with more than one resource!
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();
}
}

这可能很难相信,但即使是优秀的程序员,大多数时候也会犯错误。首先,我在Java Puzzlers[Bloch05]的第88页上弄错了,多年来没有人注意到。事实上,2007年Java类库中使用close方法的三分之二都是错误的。

即使是用try-finally语句关闭资源的正确代码,如前面两个代码示例所示,也有一个微妙的缺陷。 try-with-resources块和finally块中的代码都可以抛出异常。 例如,在firstLineOfFile方法中,由于底层物理设备发生故障,对readLine方法的调用可能会引发异常,并且由于相同的原因,调用close方法可能会失败。 在这种情况下,第二个异常完全冲掉了第一个异常。 在异常堆栈跟踪中没有第一个异常的记录,这可能使实际系统中的调试非常复杂——通常这是你想要诊断问题的第一个异常。 虽然可以编写代码来抑制第二个异常,但是实际上没有人这样做,因为它太冗长了。

当Java 7引入了try-with-resources语句时,所有这些问题一下子都得到了解决[JLS,14.20.3]。要使用这个构造,资源必须实现 AutoCloseable接口,该接口由一个返回为voidclose组成。Java类库和第三方类库中的许多类和接口现在都实现或继承了AutoCloseable接口。如果你编写的类表示必须关闭的资源,那么这个类也应该实现AutoCloseable接口。

以下是我们的第一个使用try-with-resources的示例:

// try-with-resources - the the best way to close 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 on multiple resources - short and sweet
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版本比原始版本更精简,更好的可读性,而且它们提供了更好的诊断。 考虑firstLineOfFile方法。 如果调用readLine和(不可见)close方法都抛出异常,则后一个异常将被抑制(suppressed),而不是前者。 事实上,为了保留你真正想看到的异常,可能会抑制多个异常。 这些抑制的异常没有呗被抛弃, 而是打印在堆栈跟踪中,并标注为被抑制了。 你也可以使用getSuppressed方法以编程方式访问它们,该方法在Java 7中已添加到的Throwable中。

可以在 try-with-resources语句中添加catch子句,就像在常规的try-finally语句中一样。这允许你处理异常,而不会在另一层嵌套中污染代码。作为一个稍微有些做作的例子,这里有一个版本的firstLineOfFile方法,它不会抛出异常,但是如果它不能打开或读取文件,则返回默认值:

// try-with-resources with a catch clause
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语句在编写必须关闭资源的代码时会更容易,也不会出错,而使用try-finally语句实际上是不可能的。

Effective Java 第三版——9. 使用try-with-resources语句替代try-finally语句的更多相关文章

  1. Effective Java 第三版——1. 考虑使用静态工厂方法替代构造方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  2. 《Effective Java 第三版》新条目介绍

    版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...

  3. Effective Java 第三版——3. 使用私有构造方法或枚类实现Singleton属性

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  4. Effective Java 第三版——7. 消除过期的对象引用

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  5. Effective Java 第三版——10. 重写equals方法时遵守通用约定

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  6. Effective Java 第三版——11. 重写equals方法时同时也要重写hashcode方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  7. Effective Java 第三版——12. 始终重写 toString 方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  8. Effective Java 第三版——14.考虑实现Comparable接口

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  9. Effective Java 第三版——18. 组合优于继承

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. riot.js教程【六】循环、HTML元素标签

    前文回顾 riot.js教程[五]标签嵌套.命名元素.事件.标签条件 riot.js教程[四]Mixins.HTML内嵌表达式 riot.js教程[三]访问DOM元素.使用jquery.mount输入 ...

  2. SQL Server 基本操作之三种增加法

    前言: 数据库操作避免不了对数据的操作,操作方法大同小异,万变不离其宗,今就写一下各种花式操作的根本增删改查四种操作,今天我们就来说一下增加操作的三种方法 正文: 增加操作是对数据库进行数据行的添加, ...

  3. Shell脚本数据备份

  4. 基于iframe的移动端嵌套

    需求描述 上上周接到了新的项目,移动端需要做一个底部有五个导航,点击不同的导航页面主体显示不同的页面,其中两个页面是自己做,而另外三个页面是引用另外三个网址,其中两个网址为内部项目,另外一个为外部(涉 ...

  5. 数据库—Mysql

    今天跟大家来聊聊Mysql,首先介绍一下它的历史: Mysql是一个关系型数据库管理系统,最先由瑞典的MySQL AB公司开发,后来被sun公司收购,后因sun公司又被Oracle公司收购,致使MyS ...

  6. eclipse中 web项目缺少tomcatl lib的解决办法

    1.最近在搭建的项目中,将项目导入eclipse中突然报好多错误,查看后全是丢失tomcat的lib包的错误,莫名其妙的错误. 代码中缺少的也是这样的问题 很明显,我之前的包丢了,莫名其妙的丢了. 解 ...

  7. 分布式监控系统Zabbix3.2监控数据库的连接数

    在 分布式监控系统Zabbix3.2跳坑指南 和 分布式监控系统Zabbix3.2给异常添加邮件报警 已经介绍了如何安装以及报警.此篇通过介绍监控数据库的3306端口连接数来了解如何监控其它端口和配置 ...

  8. YiShop_最全微信营销涨粉技巧

    在我们开始推广企业订阅号之前,我们必须思考微信营销策略,客户通过微信可以获得什么?企业通过微信可以得到什么?微分销专家建议企业微信定位为互动.服务工具,因为获取一个粉丝很难,可是失去一个粉丝,却是一件 ...

  9. CSS的常见问题

    1.css的编码风格 多行式:可读性越强,但是CSS文件的行数过多,影响开发速度,增大CSS文件的大小 一行式:可读性稍差,有效减少CSS文件的行数,有利于提高开发速度,减小CSS文件的大小 2.id ...

  10. MySQL用户管理及SQL语句详解

    1.1 MySQL用户管理 1.1.1 用户的定义 用户名+主机域 mysql> select user,host,password from mysql.user; +--------+--- ...