Effective Java -- 使用try-with-resources优化代码

此系列文章为本人对《Effective Java》一书的学习笔记,主要是记录对书中重点内容的理解。
既然有缘看到此文,那么希望能对你有所帮助。
本文对应原书 第9条 try-with-resources优先于try-finally

引子

相信每一位Javaer都曾经在网上拷贝过代码,很多时候你拷的内容看起来相当的凌乱,你忧心忡忡,生怕没法使用,但当你小心翼翼放入项目之中,却惊喜的发现it works

激动之余你自己研究起来,你发现代码里使用到了很多的Stream,各种tryflushfinallyclose

在Java 7之前,你可能感叹:“厉害啊,操作666”;
在Java 7以后,你应该叹息:“又是一段被时代抛弃的代码”。

缘由

Java类库中包括了很多调用close方法来手工关闭的资源,例如:

  • InputStream
  • OutputStream
  • java.sql.connection

相必不用我提大家也知道,若这些资源没有进行正常的关闭,会造成怎样的后果。
尽管这其中有很多的资源都是用终结方法作为安全网安全网可参考《Effective Java – 避免使用finalize方法》),但是终结方法本身的局限性使得效果并不如人意

所以,在早期我们需要使用try-finally来关闭资源。如:

public static String readFirstLine() throws IOException {
	BufferedReader br = new BufferedReader(new FileReader("path"));
	try {
		return br.readLine(); // 语句1
	} finally {
		br.close(); // 语句2
	}
}

这样看起来还凑合,但这毕竟只用了一个资源,如果资源数目增加,那么代码就会越发臃肿。

另外,还有一个重要的原因,就是上述代码的语句1语句2,都有可能发生异常。

举个栗子:底层的物理设备发生了异常,那么readLine方法会抛出异常,然后close方法也会发生异常,这下有趣的来了,第二个异常会把第一个异常“吃掉”(抹掉),在异常堆栈信息中,你找不到有关第一个异常的记录,这样调试会变得异常复杂。

救星

Java 7引入了try-with-resources语句,以上的问题迎刃而解。

所谓的try-with-resources,就是在try关键字后面加上一个括号,但要使用它,必须实现AutoClosable接口。
我们改造一下第一段代码:

public static String readFirstLine() throws IOException {
	try(BufferedReader br = new BufferedReader(new FileReader("path"))) {
		return br.readLine(); 
	} 
}

不仅仅变得简洁,就连上述的异常被抹掉的情况也一并处理好了。这里try-with-resources依然包含两个语句,一个是readLine方法,还有一个是隐藏的close方法。

如果这两个语句都出现了异常,那么,后一个异常会被抑制(如果是多个异常,除了第一个,后续的都会被抑制)。

这样做是为了保留你想看到的那个异常,而且这些被抑制的异常也并非被简单的丢弃了,它们依然会被打印在堆栈轨迹中,并且注明它们是被抑制的,另外通过getSuppressed方法可以访问的到(可以说是相当周到了)。

P.S. 中文版书中,对于英文原版的 “suppressed” 翻译为“禁止”,个人认为不妥,所以采用了更为广泛运用的“抑制”作为翻译。

等等,这还没完,try-with-resources还可以使用catch子句,这样可以直接轻松的处理掉异常。我们继续改造,不对异常进行抛出,而是返回一个默认值:

public static String readFirstLine() {
	try(BufferedReader br = new BufferedReader(new FileReader("path"))) {
		return br.readLine(); 
	} catch (IOException e) {
		// 省略异常打印
		return DEFAULT_VALUE;
	}
}

总结

在使用必须关闭的资源时,我们要优先使用 try-with-resources,而不是 try-finally。前者的代码编写简单且更加简洁有效,所以赶紧动手把你项目中的try-finally优化一下吧。

水平有限,若文章中存在错误,恳请不吝赐教,这对我以及后面的读者都有重要意义

©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页