关于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微服务电商我的项目教程

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理