乐趣区

关于java:为什么不推荐使用trycatchfinally处理java异常

欢送微信搜寻公众号【java 版 web 我的项目】获取资源:java 学习视频 / 设计模式笔记 / 算法手册 /java 我的项目

这篇文章是我近期看了《Effective java》一书中总结的,来自其中第九条。为了对其了解的更加透彻,因而从新剖析了一下,并退出了一些其余点。

本文的所有例子均在本地代码运行结束

基于 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》,当初要敞开资源:

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();
        }
}

如果须要敞开的资源不仅品种多,而且数量也很多。那代码可就太宏大了。当初对这种形式的毛病进行一波总结:

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、代码简单问题解决

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

能够看出这种形式代码更加简略,呈现了谬误,也能疾速定位。

2、异样抹去问题解决

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

如果 readLine 和不可见的 close 办法都抛出异样,close 办法抛出的异样就会被禁止,try-finally 解决机制中咱们无奈看到,堆栈轨迹中也不能打印,然而 try-with-resources 不一样,全副会被打印在堆栈轨迹中,并注明它们是被禁止的异样,通过编写调用 getSuppressed 办法还能够拜访到它们。当初再来测试一遍。

OK,下面基本上全副剖析结束,然而此书还给出了一个更好的案例:

static String firstLineOfFile(String path, String defaultVal) {try (BufferedReader reader = new BufferedReader(new FileReader(path))) {return reader.readLine();
        } catch (IOException e) {return defaultVal;}
}

这个 firstLineOfFile 办法没有抛出异样,然而如果它无奈关上文件,或者无奈从中读取,就会返回一个默认值。

论断

解决必须敞开的资源时,始终要优先思考应用 try-with-resources,而不是 try-finally。这样失去的代码将更简洁,清晰,产生的异样也更有价值,这些也是 try-finally 无奈做到的。

作者:愚公要移山
起源:https://www.toutiao.com/i6908…

近期热文举荐:
SpringCloud 微服务电商我的项目教程

退出移动版