首页 > 资讯 > 焦点关注

tryresources优于tryfinally?(全文共3104字)

来源: 更新时间:2022-01-12 19:52:46
The Beginning

最近在看《Effective Java》看到第九点,try-with-resources 优先于try-finally。为了理解更加透彻,个人重新分析了一下,内容如下。

在java开发中,一些网络链接或者是文件资源都需要程序员去手动调用close方法关闭,比如InputStream、OutputStream和java.sql.Connection。如果忘关了就可能造成严重的性能后果。而关闭的方法有很多种。比如finalizer、try-catch-finally、try-with-resources等等。

finalizer机制可以关闭,但是其执行性不可预测,还有可能造成内存泄漏,所以一般不使用,虽然java9还提出了cleaner机制代替了finalizer机制,但是其执行依然不可预测,因此选择就落在了try-catch-finally和try-with-resources之间。

我们先看看try-catch-finally的在不同场景下的执行顺序。

1:代码没有异常

执行顺序:try执行完整->catch不执行->finally执行

2:代码有异常且catch进行捕获

执行顺序:try执行部分->跳转catch捕获处理->finally执行

3:代码有异常且catch不捕获:这种情况没有catch

执行顺序:try执行部分->finally执行

我们可以得出一个结论,不管有没有异常,如果有finally块,那么finally块代码一定是会被执行的。

我们来看看Effective Java的案例

static String firstLineOfFile(String path) throws IOException { BufferedReader reader = new BufferedReader(new FileReader(path)); try { return reader.readLine(); } finally { reader.close(); } }

关闭一个资源还好,但是如果再添加第二个资源,代码看起来就会一团糟了。

static void copy(String src, String desc) throws IOException { InputStream in = new FileInputStream(src); try { OutputStream out = new FileOutputStream(desc); byte[] bytes = new byte[1024]; int n; try { while ((n = in.read(bytes)) != -1) { out.write(bytes, 0, n); } } finally { out.close(); } } finally { in.close(); } }

如果再添加几个不同资源, 需要关闭的资源不仅种类多,而且数量也很多。代码就显得很臃肿,而且非常不优雅,还容易出现内存泄露的问题。

当java7 引入try-with-resources语句时,所有这些问题一下子都全部解决了。要使用这个构造的资源,必须先实现AutoCloseable接口,其中包含了单个返回void的close方法。Java类库与第三方类库中的许多类和接口,现在都实现或扩展了AutoCloseable接口,如果编写了一个类,它代表的是必须被关闭的资源,那么这个类也应该实现AutoCloseable。

以下就是使用try-with-resources的第一个范例。其中BufferedReader已经实现了AutoCloseable

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

以下就是使用ry-with-resources的第二个范例。InputStream 和 OutputStream已经实现了AutoCloseable

static void copy(String src, String dst) throws IOException { try (InputStream inputStream = new FileInputStream(src); OutputStream outputStream = new FileOutputStream(dst)){ byte[] buf = new byte[1024]; while (inputStream.read(buf) >= 0){ outputStream.write(buf,0,inputStream.read(buf)); } }}

使用try-with-resources不仅使代码变得更加简洁易懂,也更容易诊断,以firstLineOfFile方法为例,如果调用readLine和不可见的close方法都抛出异常,后一个异常就会被禁止,以保留第一个异常。但是我们实际上,这些异常我们都是想它们都打印出来,可以查看堆栈轨迹的。这个时候 我们可以通过getSUppressed方法还可以访问到它们,此方法也已经添加在Java7 的Throwable中了。

经过上面例子,结论非常明显,在处理必须关闭的资源时,始终要优先考虑用try-with-resources,而不是try-finally,这样得到的代码将更加简洁,就能更轻松地正确编写代码,实践证明,这个用try-finally是不可能做到的。

THE END

TAG:顺序  异常  代码  方法  资源  

猜你喜欢

相关文章