文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

为什么不推荐使用try-catch-finally处理Java异常?

2024-12-03 13:38

关注

    “    本文的所有例子均在本地代码运行完毕

         基于JDK版本1.8,运行环境eclipse

         本文类名:TryWithResources,下文的堆栈信息也以此为基础    ”

在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-with-resources。下面带着这个答案去分析为什么推荐使用try-with-resources而不是try-finally。

一、前言

在正式分析之前,我们先看一波finally的执行顺序。

1、finally不是必要条件

也就是说try-catch-finally中,可以只有try-catch,也可以只有try-finally。

2、假设基于try-catch-finally:

第一:代码没有异常

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

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

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

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

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

从上面的执行顺序可以看出,finally语句不管在哪种情况是一定会执行的。基于这个认识,现在我们再来分析。

二、try-finally的缺点

先看案例,本案例来自《Effective java》,现在要关闭资源: 

  1. static String firstLineOfFile(String path) throws IOException {  
  2.         BufferedReader reader = new BufferedReader(new FileReader(path));  
  3.         try {  
  4.             return reader.readLine();  
  5.         } finally {  
  6.             reader.close();  
  7.         }  

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

  1. static void copy(String src, String desc) throws IOException {  
  2.         InputStream in = new FileInputStream(src);  
  3.         try {  
  4.             OutputStream out = new FileOutputStream(desc);  
  5.             byte[] bytes = new byte[1024];  
  6.             int n;  
  7.             try {  
  8.                 while ((n = in.read(bytes)) != -1) {  
  9.                     out.write(bytes, 0, n);  
  10.                 }  
  11.             } finally {  
  12.                 out.close(); 
  13.             }  
  14.         } finally {  
  15.             in.close();  
  16.         }  

如果需要关闭的资源不仅种类多,而且数量也很多。那代码可就太庞大了。现在对这种方式的缺点进行一波总结:

1. 关闭的资源多事,代码复杂

2. 对于第一个案例,如果设备出现异常,那么那么调用readLine就会抛出异常,同时close方法也出现异常,在这种情况下,close异常会完全抹去readLine异常。在异常堆栈轨迹中也完全没有readLine异常的记录。

现在来测试一边:

基于以上原因,出现了try-with-resources。

三、try-with-resources的优势

try-with-resources是在jdk1.7引入的,可以完美解决以上的问题。要使用这个构造的资源,必须先实现AutoCloseable接口,其中包含了单个返回void的close方法,Java类库与第三方类库中的许多类和接口,现在都实现或扩展了AutoCloseable接口,因此我们现在不必实现了。

既然try-with-resources能够解决以上的问题,现在来看一下,如何解决的:

1、代码复杂问题解决 

  1. static void copy(String src, String desc) throws IOException {  
  2.         try (InputStream in = new FileInputStream(src);  
  3.              OutputStream out = new FileOutputStream(desc)) {  
  4.             byte[] bytes = new byte[1024];  
  5.             int n;  
  6.             while ((n = in.read(bytes)) != -1) {  
  7.                 out.write(bytes, 0, n);  
  8.             }  
  9.         }  

可以看出这种方式代码更加简单,出现了错误,也能快速定位。

2、异常抹去问题解决 

  1. static String firstLineOfFil  (String path) throws IOException {  
  2.         try (BufferedReader reader = new BufferedReader(new FileReader(path))) {  
  3.             return reader.readLine();  
  4.         } 
  5.  

如果readLine和不可见的close方法都抛出异常,close方法抛出的异常就会被禁止,try-finally处理机制中我们无法看到,堆栈轨迹中也不能打印,但是try-with-resources不一样,全部会被打印在堆栈轨迹中,并注明它们是被禁止的异常,通过编写调用getSuppressed方法还可以访问到它们。现在再来测试一遍。

OK,上面基本上全部分析完毕,但是此书还给出了一个更好的案例: 

  1. static String firstLineOfFile(String path, String defaultVal) {  
  2.         try (BufferedReader reader = new BufferedReader(new FileReader(path))) {  
  3.             return reader.readLine();  
  4.         } catch (IOException e) {  
  5.             return defaultVal; 
  6.          }  

这个firstLineOfFile方法没有抛出异常,但是如果它无法打开文件,或者无法从中读取,就会返回一个默认值。

结论

处理必须关闭的资源时,始终要优先考虑使用try-with-resources,而不是try-finally。这样得到的代码将更简洁,清晰,产生的异常也更有价值,这些也是try-finally无法做到的。 

来源:java版web项目内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯