Effective|Effective Java(3rd)-Item9:try-with-resources比try-finally更好

??Java库包括了许多必须通过调用关闭方法被手动关闭的资源。比如 InputStream, OutputStream和java.sql.Connection。关闭资源经常被客户端忽略,可预见的会有可怕的性能问题。虽然许多资源使用finalizer作为安全保障,但是finalizer并不能很好地工作item8)
??从历史上看,try-finally语句是保障资源关闭最好的方式,即使面对异常或返回:

Effective|Effective Java(3rd)-Item9:try-with-resources比try-finally更好
文章图片
image.png
??这看起来并不糟糕,但是当你添加第二个资源时就会变糟:

Effective|Effective Java(3rd)-Item9:try-with-resources比try-finally更好
文章图片
image.png ??这可能很难相信,但是即使是优秀的程序员在大多数的时候也有会弄错。起先,我在Java Puzzlers的88页上就搞错了,多年来没人注意到。事实上,2007年三分之二的Java库中关闭方法的使用都是错误的。
??即使是使用try-finally语句关闭资源的正确代码,正如前两个代码的例子,也有一个微妙的缺陷。try和finally块也有可能抛出异常。例如,在firstLineOfFile 方法中,readLine的调用可能会由于底层物理设备的故障抛出异常,由于同样的原因,调用关闭方法也有可能会失败。在这种情况下,第二个异常完全抹杀了第一个异常。异常堆栈跟踪中没有第一个异常的记录,这可能极大地使在真实系统中的调试复杂化-通常这是你要去查看以诊断问题的第一个异常。虽然有可能通过编写代码来抑制第二个异常而有利于第一个异常,但是几乎没人这样做,因为这样的代码太冗长了。
??当Java7引入了try-with-resource语句时,所有的这些问题都被一举解决了。如果要使用这个构造方法的使用,资源必须实现AutoCloseable 接口,该接口包含了单个返回void的关闭方法。许多在Java库和第三方库的类和接口现在都继承或实现了AutoCloseable。如果你编写的类代表这个资源必须被关闭,你的类也应该实现AutoCloseable 。
??这是我们的第一个使用try-with-resource的例子:

Effective|Effective Java(3rd)-Item9:try-with-resources比try-finally更好
文章图片
image.png
??这是第二个使用try-with-resource的例子:

Effective|Effective Java(3rd)-Item9:try-with-resources比try-finally更好
文章图片
image.png ??try-with-resources的版本不仅比原先的版本更短,而且更易读,而且它们提供了更好的诊断功能。考虑firstLineOfFile方法,如果readLine和(不可见)close都抛出异常,后一个异常被抑制而有利于前者。事实上,可以抑制多个异常来保留你实际想查看的异常。这些异常不仅被丢弃,而且它们还被打印在堆栈跟踪表示它们被抑制。你也可以以编程的形式用getSuppressed方法来查看它们,该方法已被加入Java7的Throwable中。
??你也可以将catch语句放到try-with-resources 语句之中,就像之前常规的try-finally语句中一样。这允许你不通过嵌套另一层而污染代码来处理异常。作为一个有点做作的方法,这里有一个不抛出异常的firstLineOfFile 方法的版本,如果不能打开文件或从中读取,返回一个默认值:

Effective|Effective Java(3rd)-Item9:try-with-resources比try-finally更好
文章图片
image.png ??
这个课程很清楚:当处理必须要被关闭资源的情况时,优先使用try-with-resource而不是try-finally。最终的代码又短又清晰,生成的异常更有用。try-with-resources 语句很容易编写正确代码来关闭必须关闭的资源,使用 try-finally几乎是不可能的。
【Effective|Effective Java(3rd)-Item9:try-with-resources比try-finally更好】本文写于2019.1.24,历时1天

    推荐阅读