异常中finally是在return前呢,还是return后

「这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战」。

茫茫人海千千万万,感谢这一秒你看到这里。希望我的文章对你的有所帮助!

愿你在未来的日子,保持热爱,奔赴山海!

题记:昨天我们偷偷留了一个问题,finally是在return前呢,还是return后呢?这个有人知道吗?没关系今天就来揭晓答案啦! 冲冲冲!

😮问题:finally是在return前呢,还是return后呢?

  • 让我们看下面的代码?

    public class TryCatchFinallyDemo2 {
        public static void main(String[] args) {
    //        test();
            System.out.println(test2()); // 我有执行到吗 try
            System.out.println(test3()); // 我有执行到吗 catch
        }
    ​
        public static String test3() {
            String str = "";
            try {
                str = "try";
                System.out.println(10 / 0);
                return str;
            }catch(Exception e) {
                str = "catch";
                return str;
            }finally {
                str = "finally";
                System.out.println("我有执行到吗");
            }
        }
    ​
        public static String test2() {
            String str = "";
            try {
                str = "try";
                return str;
            }catch(Exception e) {
                str = "catch";
                return str;
            }finally {
                str = "finally";
                System.out.println("我有执行到吗");
            }
        }
    }
    复制代码

    运行结果:

    我有执行到吗
    try
    我有执行到吗
    catch
    复制代码

    看到这里发现无论是否异常,finally都会执行,但是都在在return之前就执行了代码。可是可是,为什么返回出来的字符串不是finally呢?让我们一起来思考思考:

    • 我们看test2()方法,程序执行try语句块,把变量str赋值为"try",由于没有发现异常,接下来执行finally语句块,把变量str赋值为"finally",然后return str,则t的值是finally,最后str的值就是"finally",程序结果应该显示finally,但是实际结果为“try”

    • 实际上,在try语句的return块中,当我们执行到return str这一步的时候呢,这里不是return str 而是return “try”了,这个放回路径就已经形成了。

      相当于return返回的引用变量(str是引用类型)并不是try语句外定义的引用变量str,而是系统重新定义了一个局部引用str2 ,返回指向了引用str2 对应的值,也就是"try"字符串。

      但是到这里呢,它发现后面还有finally,所以继续执行finally的内容,str = "finally"; System.out.println("我有执行到吗");, 再次回到以前的路径,继续走return “try”,形成返回路径之后,这里的return的返回引用就不是变量str 了,而是str2引用的值"try"字符串。

    是不是对这个现象有了一定的了解。嘿嘿,这里我们再转换下:

    public class TryCatchFinallyDemo2 {
        public static void main(String[] args) {
    //        test();
    //        System.out.println(test2()); // try
    //        System.out.println(test3()); // catch
            System.out.println(test4()); 
    ​
        }
    ​
        public static String test4() {
            String str = "";
            try {
                str = "try";
                return str;
            }catch(Exception e) {
                str = "catch";
                return str;
            }finally {
                str = "finally";
                return str;
            }
        }
    }
    复制代码

    这里我们猜测下,结果是什么呢?

    运行结果:finally

    • 我们发现try语句中的return语句给忽略。可能JVM认为一个方法里面有两个return语句并没有太大的意义,所以try中的return语句给忽略了,直接起作用的是最后finally中的return语句,就又重新形成了一条返回路径,所以这次返回的是“finally”字符串。

    再看一下: 我们是不是知道finally语句是一定执行的,但是能有办法使他不执行吗?

    既然我说了,那么就是一定有的啦。

    public class TryCatchFinallyDemo3 {
        public static void main(String[] args) {
            try{
                System.out.println(10 / 0);
            }catch(Exception e) {
                e.printStackTrace();
                System.exit(0);
            }finally {
                System.out.println("finally我有执行到吗");
            }
        }
    }
    复制代码

    执行结果:

    java.lang.ArithmeticException: / by zero
        at com.it.test3.TryCatchFinallyDemo3.main(TryCatchFinallyDemo3.java:6)
    复制代码

    可以发现:

    当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。

🌸总结

相信各位看官都对异常处理机制的概念有了更加深入的了解吧,明天我们就对异常处理机制做个总结呗!那我们继续期待下一章的异常更多的内容吧!欢迎期待下一章的到来!

让我们也一起加油吧!本人不才,如有什么缺漏、错误的地方,也欢迎各位人才大佬评论中批评指正!当然如果这篇文章确定对你有点小小帮助的话,也请亲切可爱的人才大佬们给个点赞、收藏下吧,一键三连,非常感谢!

学到这里,今天的世界打烊了,晚安!虽然这篇文章完结了,但是我还在,永不完结。我会努力保持写文章。来日方长,何惧车遥马慢!

感谢各位看到这里!愿你韶华不负,青春无悔!

\