Java库包含许多必须通过调用close方法手动关闭的资源。 示例包括InputStream,OutputStream和java.sql.Connection。 关闭资源经常被客户忽视,可预见的可怕性能后果。 虽然其中许多资源使用终结方法作为安全网,但终结方法不能很好地工作(第8项)。

  在之前的做法中(Historically),try-finally语句是保证资源正确关闭的最佳方式,即使出现异常或在return的时候(even in the face of an exception or return):

// 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块和finally块中的代码都能够抛出异常。 例如,在firstLineOfFile方法中,对readLine的调用可能由于底层物理设备中的故障而引发异常,并且由于相同的原因,对close的调用可能会失败。 在这种情况下,第二个异常完全覆盖了第一个异常。 异常堆栈跟踪中没有第一个异常的记录,这可能会使实际系统中的调试变得非常复杂 - 通常第一个异常才是你要查看并诊断问题的关键所在(usually it’s the first exception that you want to see in order to diagnose the problem)。虽然有可能编写代码来抑制第二个异常而支持第一个异常,但几乎没有人这样做,因为它太冗长了。

  当Java 7引入了try-with-resources语句[JLS,14.20.3]时,所有这些问题都得到了一举解决。 要使用此构造,资源必须实现AutoCloseable接口,该接口由单个返回类型为void的close方法组成。 Java库和第三方库中的许多类和接口现在实现或继承AutoCloseable。 如果编写一个代表必须关闭的资源的类( If you write a class that represents a resource that must be closed),那么你的类也应该实现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调用和关闭(不可见)资源时抛出异常,则后一个异常被抑制而有利于前者(the latter exception is suppressed in favor of the former)。 实际上,可以抑制多个异常以保留你实际想要查看的异常。 这些被抑制的异常不是被丢弃; 它们被打印在跟踪的堆栈中,并带有一个表示它们被压制了的符号。 你还可以使用getSuppressed方法以编程的方式访问它们,该方法已添加到Java 7中的Throwable中。

  你可以将try子句放在try-with-resources语句中,就像在常规的try-finally语句中一样。 这允许你处理异常,而不会使用另一层嵌套来破坏你的代码。 作为一个有点设计想法的例子(As a slightly contrived example),这里是我们的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;
}
}

  这里经验教训是很明确的(The lesson is clear):在处理必须关闭的资源时,相比于try-finally,始终优先使用try-with-resources。 生成的代码更短更清晰,它生成的异常更有用。 try-with-resources语句可以在使用必须关闭的资源的同同时轻松编写正确的代码,使用try-finally几乎是不可能的。

关注个人公众号获取更新!

第9项:尽量使用try-with-resources而不是try-finally(Prefer try-with-resources to try-finally)的更多相关文章

  1. java resources 红叉 An error occurred while filtering resources

    用eclipse创建了一个Spring mvc的Maven项目,在项目上有个叉叉,通过Window -> Show View -> Markers中看到错误原因 An error occu ...

  2. 条款一:尽量使用const、inline而不是#define

    #define ASPECT_RATIO 1.653 编译器会永远也看不到ASPECT_RATIO这个符号名,因为在源码进入编译器之前,它会被预处理程序去掉,于是ASPECT_RATIO不会加入到符号 ...

  3. Spring Security – security none, filters none, access permitAll

    1.概述 Spring Security提供了几种将请求模式配置为不安全或允许所有访问的机制.取决于这些机制中的哪一种 - 这可能意味着根本不在该路径上运行安全过滤器链,或者运行过滤器链并允许访问 2 ...

  4. WPF学习之资源-Resources

    WPF学习之资源-Resources WPF通过资源来保存一些可以被重复利用的样式,对象定义以及一些传统的资源如二进制数据,图片等等,而在其支持上也更能体现出这些资源定义的优越性.比如通过Resour ...

  5. 在后台代码中动态生成pivot项并设置EventTrigger和Action的绑定

    最近在做今日头条WP的过程中,遇到需要动态生成Pivot项的问题.第一个版本是把几个频道写死在xaml里了,事件绑定也写在xaml里,每个频道绑定一个ObservableCollection<A ...

  6. [安卓]应用程序资源(App Resources)

    谷歌推荐我们,在开发安卓系统应用程序的时候,要把资源从代码中分离出来,这样便于我们单独维护它们.采取分离的资源设计,我们还可以提供可选资源,支持特定的设备配置譬如不同的语言或屏幕尺寸,随着越来越多的A ...

  7. 利用maven中resources插件的copy-resources目标进行资源copy和过滤

    maven用可以利用如下配置进行资源过滤,pom.xml的配置如下: <build> <!-- 主资源目录 --> <resources> <resource ...

  8. Unity Android 5.6版本Resources.Load效率的问题

    0x00 前言 相信不少使用Unity的小伙伴都听说过,甚至也亲身经历过在Unity5.6最初的几个版本中使用Resources.Load方法加载资源变--慢的问题. 这个问题的确是存在的,比如这个i ...

  9. 手把手教你解析Resources.arsc

    http://blog.csdn.net/beyond702/article/details/51744082 一.前言 对于APK里面的Resources.arsc文件大家应该都知道是干什么的(不知 ...

  10. 解析Resources.arsc

    一.前言 对于APK里面的Resources.arsc文件大家应该都知道是干什么的(不知道的请看我的另一篇文章Android应用程序资源文件的编译和打包原理),它实际上就是App的资源索引表.下面我会 ...

随机推荐

  1. ubuntu12上部署Django1.8.4+uwsgi+nginx超级详细流程配置到云服务器

    环境: 系统:ubuntu12,系统自带默认有python2.7 框架:Django1.8.4,需要python2.7以上才能支持   前言: 用户浏览器发送http请求->nginx(静态文件 ...

  2. (转)css 背景色渐变兼容写法

    css3:linear-gradient 比如:黑色渐变到白色,代码如下: .gradient{ background: -moz-linear-gradient(top, #000000 0%, # ...

  3. List扩展方法汇总(仅备注)

    不管在c/s还是b/s的c#语言开发程序中,经常会用到List的扩展方法,尤其在json格式的数据和服务端交互越来越流行,很多时候总是在开发使用到的时候才去搜索有些扩展方法或者linq的用法,在这里, ...

  4. 2009-2010网络最热的&nbsp;嵌入式…

    前段时间做了一个关于ARM9 2440资料的汇总帖,很高兴看到21ic和CSDN等论坛朋友们的支持和鼓励.当年学单片机的时候datasheet和学习资料基本都是在论坛上找到的,也遇到很多好心的高手朋友 ...

  5. 管理授权&管理决策&管理组织&管理目标

    [管理授权] 1.如果一个管理者不明白为公司培养人的责任,就很可能成为公司的瓶颈.这个问题的解决在于让管理者学会“授权”,把大部分自己紧抓不放的事情下放给部门内其他人做. 2.为一件事负责和亲自做是两 ...

  6. Linux 安装(重装)mysql

    1 新建存放mysql相关文件的文件夹 mkdir -p /export/servers/mysql //存放mysql相关的几个rpm文件 2 查看原有mysql 并卸载 rpm -qa | gre ...

  7. 虚拟机安装CentOS以及SecureCRT设置【完美无错版】

    一.CentOS简介 CentOS是Linux的发行版之一,它安全.稳定.高效,是我最喜欢的Linux发行版之一.CentOS根据Red Hat Enterprise Linux开放源代码编译而成,与 ...

  8. Setting up an OpenGL development environment in ubuntu

    1.opening terminal window and entering the apt-get command for the packages: sudo apt-get install me ...

  9. SP1557 GSS2 - Can you answer these queries II

    一开始看不懂题解,看懂了题解之后觉得还是挺妙的. 好多题解里都提到了HH的项链,但是我觉得关系并不大啊…… 先把所有询问离线下来按照右端点排序,按照询问的要求一个一个加入数字,怎么加入数字,我们设计一 ...

  10. A. Xor-tree

    题目意思: 给一颗n个节点的树,每个节点有一个值要么是0要么是1,改变某个节点的值时,它的儿子不变,它儿子的儿子翻转,它儿子的儿子的儿子不变,如此类推.给定各个节点的目标值,求最少的翻转次数,使得达到 ...