来源: 最后更新:22-01-12 07:52:46
最近在看《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是不可能做到的。
仅20年就变危房!杭州这套480㎡独栋别墅想重建,背后有何玄机
国防部新闻发言人谭克非就美方武力袭击中国民用无人飞艇发表谈话
以色列媒体:贝内特回忆称,普京曾保证“不会杀死泽连斯基”
2023南阳元宵节烟花晚会直播时间+入口(元宵节南阳有什么活动)
2023南阳元宵节焰火晚会直播在哪看(2021南阳电视台少儿春晚直播)
“退休后看了20年电视,很没意思!”80岁老夫妻开电动三轮房车环游中国
港媒:港警止暴制乱行动擒暴最多“战役”细节首次披露
旅美大熊猫“乐乐”回国前突然离世,中方赴美调查
巴基斯坦前总统穆沙拉夫去世
热搜第一!父亲借女儿3万元压岁钱不还被起诉,法院判了
药物流产疼不疼的真相 过来人分享了自己最真实的经验药物流产,它是意外怀孕以后的处理方式之一。大多数女性朋友出现意
国际高中怎么样(领科国际高中怎么样) 蜂胶怎么样 蜂胶怎么用 有效身份证件类别填写什么 办理出生公证委托书 为什么来白带会有血 妇科专家来告诉你主要原因