Return出现在try、catch、finally中的不同执行结果

Stella981
• 阅读 415

前几天,去一家公司面试,碰到一道面试题大致内容为:如果在try中存在return语句,那么finally中的语句是否会执行,如果会执行,那先后顺序又是怎样。

当时自己的解题思路是:坚信大学时候,java编程基础的一句话,finally中的语句一定会执行,所以我觉得finally中的语句一定会执行,而return语句会跳出当前方法,所以return语句应该在finally语句执行完毕以后,再执行,否则return跳出以后,finally中的东西肯定是没办法执行的。

于是我查了一些资料,总结了几个情况。

首先,return可以出现在try、catch、finally、以及方法的最后,由于return在finally中,需要使用@SuppressWarnings("finally"),也是不推荐的做法,所以可行的做法为下列四种.

1  return在try和函数的最后出现一次

2  return在catch和函数的最后出现一次

3  return在try和catch中出现

4. return在方法最后出现

       1 
 
     
     /*
 
     
     

 
     
       2 
 
     
      * Copyright 2008-2014 the original author or authors.

 
     
       3 
 
     
      *

 
     
       4 
 
     
      * Licensed under the Apache License, Version 2.0 (the "License");

 
     
       5 
 
     
      * you may not use this file except in compliance with the License.

 
     
       6 
 
     
      * You may obtain a copy of the License at

 
     
       7 
 
     
      *

 
     
       8 
 
     
      *      
 
     
     http://www.apache.org/licenses/LICENSE-2.0
 
     
     

 
     
       9 
 
     
      *

 
     
      10 
 
     
      * Unless required by applicable law or agreed to in writing, software

 
     
      11 
 
     
      * distributed under the License is distributed on an "AS IS" BASIS,

 
     
      12 
 
     
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 
     
      13 
 
     
      * See the License for the specific language governing permissions and

 
     
      14 
 
     
      * limitations under the License.

 
     
      15 
 
     
      
 
     
     */
 
     
     

 
     
      16 
 
     
     
 
     
     package
 
     
      com.app.spring.test;

 
     
      17 
 
     
     

 
     
      18 
 
     
     
 
     
     /**
 
     
     

 
     
      19 
 
     
      * TestTryCatchReturn

 
     
      20 
 
     
      * <h1>return可以出现在try、catch、finally、以及方法的最后</h1>

 
     
      21 
 
     
      * <h1>由于return在finally中,需要使用@SuppressWarnings("finally"),也是不推荐的做法</h1>

 
     
      22 
 
     
      * 所以可行的做法为下列四种

 
     
      23 
 
     
      * <ul>

 
     
      24 
 
     
      *     <li>return在try和函数的最后出现一次</li>

 
     
      25 
 
     
      *     <li>return在catch和函数的最后出现一次</li>

 
     
      26 
 
     
      *     <li>return在try和catch中出现</li>

 
     
      27 
 
     
      *     <li>return在方法最后出现</li>

 
     
      28 
 
     
      * </ul>

 
     
      29 
 
     
      * 
 
     
     @author
 
     
      李长伟

 
     
      30 
 
     
      * 
 
     
     @version
 
     
      1.0 创建时间  2015年7月27日 下午2:04:17

 
     
      31 
 
     
      *

 
     
      32 
 
     
      
 
     
     */
 
     
     

 
     
      33 
 
     
     
 
     
     public
 
     
      
 
     
     class
 
     
      TestTryCatchReturn {

 
     
      34 
 
     
         

 
     
      35 
 
     
         
 
     
     /**
 
     
     

 
     
      36 
 
     
          * try中有return,finally中没有return

 
     
      37 
 
     
          * 先执行finally中的语句

 
     
      38 
 
     
          * 然后再执行try中的return

 
     
      39 
 
     
          * 
 
     
     @return
 
     
     

 
     
      40 
 
     
          
 
     
     */
 
     
     

 
     
      41 
 
     
         
 
     
     public
 
     
      
 
     
     static
 
     
      String testTryReturnFinally() {

 
     
      42 
 
     
             
 
     
     try
 
     
      {

 
     
      43 
 
     
                 
 
     
     return
 
     
      
 
     
     "
 
     
     try返回
 
     
     "
 
     
     ;

 
     
      44 
 
     
             } 
 
     
     catch
 
     
      (Exception e) {

 
     
      45 
 
     
                 e.printStackTrace();

 
     
      46 
 
     
             } 
 
     
     finally
 
     
      {

 
     
      47 
 
     
                 System.out.println(
 
     
     "
 
     
     执行finally
 
     
     "
 
     
     );

 
     
      48 
 
     
             }

 
     
      49 
 
     
             
 
     
     return
 
     
      
 
     
     "
 
     
     退出try catch返回
 
     
     "
 
     
     ;

 
     
      50 
 
     
         }

 
     
      51 
 
     
         

 
     
      52 
 
     
         
 
     
     /**
 
     
     

 
     
      53 
 
     
          * try和finally中均有return

 
     
      54 
 
     
          * 先执行try中的语句

 
     
      55 
 
     
          * 然后再执行finally中的语句

 
     
      56 
 
     
          * 最后执行finally中的return语句

 
     
      57 
 
     
          * 
 
     
     @return
 
     
     

 
     
      58 
 
     
          
 
     
     */
 
     
     

 
     
      59 
 
     
         @SuppressWarnings(
 
     
     "
 
     
     finally
 
     
     "
 
     
     )

 
     
      60 
 
     
         
 
     
     public
 
     
      
 
     
     static
 
     
      String testTryReturnFinallyReturn() {

 
     
      61 
 
     
             
 
     
     try
 
     
      {

 
     
      62 
 
     
                 System.out.println(
 
     
     "
 
     
     执行try
 
     
     "
 
     
     );

 
     
      63 
 
     
                 
 
     
     return
 
     
      
 
     
     "
 
     
     try返回
 
     
     "
 
     
     ;

 
     
      64 
 
     
             } 
 
     
     catch
 
     
      (Exception e) {

 
     
      65 
 
     
                 e.printStackTrace();

 
     
      66 
 
     
             } 
 
     
     finally
 
     
      {

 
     
      67 
 
     
                 System.out.println(
 
     
     "
 
     
     执行finally
 
     
     "
 
     
     );

 
     
      68 
 
     
                 
 
     
     return
 
     
      
 
     
     "
 
     
     finally返回
 
     
     "
 
     
     ;

 
     
      69 
 
     
             }

 
     
      70 
 
     
         }

 
     
      71 
 
     
         

 
     
      72 
 
     
         
 
     
     /**
 
     
     

 
     
      73 
 
     
          * try中有return,finally中没有return,且存在修改变量的值

 
     
      74 
 
     
          * 先执行try中的语句,修改值,并且也会执行return语句中修改值的操作

 
     
      75 
 
     
          * 然后再执行finally中的语句,修改值,但是如果finally中没有return语句的话

 
     
      76 
 
     
          * finally的修改无法影响到try中的return的返回值

 
     
      77 
 
     
          * 
 
     
     @return
 
     
     

 
     
      78 
 
     
          
 
     
     */
 
     
     

 
     
      79 
 
     
         
 
     
     public
 
     
      
 
     
     static
 
     
      String testTryReturnFinallyBasic() {

 
     
      80 
 
     
             
 
     
     int
 
     
      i 
 
     
     =
 
     
      
 
     
     10
 
     
     ;

 
     
      81 
 
     
             
 
     
     try
 
     
      {

 
     
      82 
 
     
                 i 
 
     
     +=
 
     
      
 
     
     10
 
     
     ;

 
     
      83 
 
     
                 
 
     
     return
 
     
      
 
     
     "
 
     
     try返回
 
     
     "
 
     
      
 
     
     +
 
     
      i;

 
     
      84 
 
     
             } 
 
     
     catch
 
     
      (Exception e) {

 
     
      85 
 
     
                 e.printStackTrace();

 
     
      86 
 
     
             } 
 
     
     finally
 
     
      {

 
     
      87 
 
     
                 i 
 
     
     -=
 
     
      
 
     
     10
 
     
     ;

 
     
      88 
 
     
                 System.out.println(
 
     
     "
 
     
     执行finally
 
     
     "
 
     
      
 
     
     +
 
     
      i);

 
     
      89 
 
     
             }

 
     
      90 
 
     
             
 
     
     return
 
     
      
 
     
     "
 
     
     退出try catch返回
 
     
     "
 
     
     ;

 
     
      91 
 
     
         }

 
     
      92 
 
     
         

 
     
      93 
 
     
         
 
     
     /**
 
     
     

 
     
      94 
 
     
          * try中有return,finally中没有return,且存在修改对象的值

 
     
      95 
 
     
          * 先执行try中的语句,修改值,并且也会执行return语句中修改对象的操作

 
     
      96 
 
     
          * 然后再执行finally中的语句,修改值,但是如果finally中没有return语句的话

 
     
      97 
 
     
          * finally的修改可以影响到try中的return的返回值

 
     
      98 
 
     
          * 
 
     
     @return
 
     
     

 
     
      99 
 
     
          
 
     
     */
 
     
     

 
     
     100 
 
     
         
 
     
     public
 
     
      
 
     
     static
 
     
      Num testTryReturnFinallyObject() {

 
     
     101 
 
     
             Num num 
 
     
     =
 
     
      
 
     
     new
 
     
      TestTryCatchReturn().
 
     
     new
 
     
      Num();

 
     
     102 
 
     
             
 
     
     try
 
     
      {

 
     
     103 
 
     
                 num.i 
 
     
     +=
 
     
      
 
     
     10
 
     
     ;

 
     
     104 
 
     
                 System.out.println(
 
     
     "
 
     
     执行try
 
     
     "
 
     
      
 
     
     +
 
     
      num.i);

 
     
     105 
 
     
                 
 
     
     return
 
     
      num;

 
     
     106 
 
     
             } 
 
     
     catch
 
     
      (Exception e) {

 
     
     107 
 
     
                 e.printStackTrace();

 
     
     108 
 
     
             } 
 
     
     finally
 
     
      {

 
     
     109 
 
     
                 num.i 
 
     
     -=
 
     
      
 
     
     10
 
     
     ;

 
     
     110 
 
     
                 System.out.println(
 
     
     "
 
     
     执行finally
 
     
     "
 
     
      
 
     
     +
 
     
      num.i);

 
     
     111 
 
     
             }

 
     
     112 
 
     
             
 
     
     return
 
     
      num;

 
     
     113 
 
     
         }

 
     
     114 
 
     
         

 
     
     115 
 
     
         
 
     
     class
 
     
      Num {

 
     
     116 
 
     
             
 
     
     private
 
     
      
 
     
     int
 
     
      i 
 
     
     =
 
     
      
 
     
     10
 
     
     ;

 
     
     117 
 
     
         }

 
     
     118 
 
     
         

 
     
     119 
 
     
         
 
     
     public
 
     
      
 
     
     static
 
     
      
 
     
     void
 
     
      main(String[] args) {

 
     
     120 
 
     
             System.out.println(
 
     
     "
 
     
     =========1============
 
     
     "
 
     
     );

 
     
     121 
 
     
             System.out.println(testTryReturnFinally());

 
     
     122 
 
     
             System.out.println(
 
     
     "
 
     
     =========1============
 
     
     "
 
     
     );

 
     
     123 
 
     
             System.out.println(
 
     
     "
 
     
     =========2============
 
     
     "
 
     
     );

 
     
     124 
 
     
             System.out.println(testTryReturnFinallyReturn());

 
     
     125 
 
     
             System.out.println(
 
     
     "
 
     
     =========2============
 
     
     "
 
     
     );

 
     
     126 
 
     
             System.out.println(
 
     
     "
 
     
     =========3============
 
     
     "
 
     
     );

 
     
     127 
 
     
             System.out.println(testTryReturnFinallyBasic());

 
     
     128 
 
     
             System.out.println(
 
     
     "
 
     
     =========3============
 
     
     "
 
     
     );

 
     
     129 
 
     
             System.out.println(
 
     
     "
 
     
     =========4============
 
     
     "
 
     
     );

 
     
     130 
 
     
             System.out.println(testTryReturnFinallyObject().i);

 
     
     131 
 
     
             System.out.println(
 
     
     "
 
     
     =========4============
 
     
     "
 
     
     );

 
     
     132 
 
     
         }

 
     
     133 
 
     
     }

 
     
     134 
 
     
     

    
    

执行结果如下

=========1============
执行finally
try返回
=========1============
=========2============
执行try
执行finally
finally返回
=========2============
=========3============
执行finally10
try返回20
=========3============
=========4============
执行try20
执行finally10
10
=========4============

在上面的代码中我测试了4种情况,由于return出现在try或者catch中对于程序的执行结果是没有影响的,所以程序中并没有测试return在catch中的情况

  1. return在try和方法的最后,看结果很容易看出,finally中的语句先执行了,try中return的语句最后执行,而方法最后面的return并没有执行,因为已经跳出方法体了

  2. try和finally中均有return语句,try中的方法执行,但是return没有返回,然后执行finally里面的方法,最后执行finally中的return,try中的return不执行

  3. 这里的情况其实和1里面是一样的,只不过添加了一个变量的修改,从结果可以看出,catch里面对i进行了加10的操作,finally对i做了减10的操作,尽管在finally中打印的结果是10,但是最后方法的返回值依然是20,所以如果return在try和catch中,finally对变量的修改不会影响到方法最后的返回值

  4. 这里的情况和3类似,只不过把对基本类型变量的修改,变成了对象的修改,唯一的不同是finally的修改对于对象类型的变量会保留,并在返回值中体现

程序的结果,其实个人感觉还是有一些疑问,例如我也测试过直接在try中的return后面跟(i += 10)操作,发现这个操作其实是在finally之前执行的,只是跳出方法体这个操作是在finally之后执行的,所以如果把3的代码中对i的操作放在return后面,结果是一样的

还有一个问题是,尽管4中最后返回的num对象的i值受到了finally中代码的影响,但是如果返回的是String类型,结果依然是20

对于上面的疑问,还是需要对于Java虚拟机有一个深刻的理解以后才能更清楚

引用别人的一句话

对以上情况的分析,需要深入JVM虚拟机中程序执行时对CLR栈的操作情况,可以参考《深入Java虚拟机:JVM高级特性与最佳实践》一书。

点赞
收藏
评论区
推荐文章
Karen110 Karen110
2年前
一篇文章带你了解JavaScript错误处理
大家好,我是前端进阶者。执行JavaScript代码时,可能会发生意想不到的错误。错误可以是程序员编写的编码错误,由于输入错误引起的错误以及其他不可预见的事情。因此,为了处理错误,JavaScript提供了4个关键字。一、JavaScripttry...catch语句try语句允许定义一个代码块,该代码块在执行时将进行错误测试,catch如果try块中
Karen110 Karen110
2年前
一篇文章带你了解JavaScript switch
Switch是与if...else...相同的条件语句,不同之处在于switch语句允许根据值列表测试变量是否相等。switch语句用于根据不同的条件执行不同的操作。一、Switch语句使用switch语句选择要执行的多个代码块中的一个。1\.语法switch(expression)casen:codeblock
Wesley13 Wesley13
2年前
janusgraph
精确查询语句含义测试语句执行时间查询顶点标签为FALV的顶点数量g.V().hasLabel('FALV').count()2400s查询顶点属性中id为19012201clockWithResult(1){g.V().has('id','19012201')}0.18540099999999998s查询顶点属性中
Wesley13 Wesley13
2年前
Java 项目中如何使用异常
1.早抛出,晚捕获.2.如果finally语句中有return语句,则finally中的return语句将会覆盖try中的return语句,如以下代码,将会输出1。如果在finally语句里有抛出异常,那么此异常将会覆盖try块中抛出的异常。publicclassFinallyReturnTest{
Stella981 Stella981
2年前
Python从入门到入土
异常处理tryexcept在Python中,异常处理,主要是tryexcept语句,通常语法格式如下.try:代码块1exceptExceptionase:print(e)代码2try语句按照如下方式工作;首先,执行try子句(在关键字try和关键字except之间的语句)如果没有异常
Wesley13 Wesley13
2年前
Java笔试面试总结—try、catch、finally语句中有return 的各类情况
前言之前在刷笔试题和面试的时候经常会遇到或者被问到trycatchfinally语法块的执行顺序等问题,今天就抽空整理了一下这个知识点,然后记录下来。正文本篇文章主要是通过举例的方式来阐述各种情况,我这里根据trycatchfinally语法块分为两种大情况讨论:trycatch语法块和trycat
Wesley13 Wesley13
2年前
thinkPHP框架中执行原生SQL语句的方法
这篇文章主要介绍了thinkPHP框架中执行原生SQL语句的方法,结合实例形式分析了thinkPHP中执行原生SQL语句的相关操作技巧,并简单分析了query与execute方法的使用区别,需要的朋友可以参考下本文实例讲述了thinkPHP框架中执行原生SQL语句的方法。分享给大家供大家参考,具体如下:怎样在thinkphp里面执行原生的sql语句?
LeeFJ LeeFJ
1年前
Foxnic-SQL (13) —— 外部SQL与SQL模版
首先,大多数时候,我们的第一反应是用字符串去拼接SQL语句,这说明字符串拼接方式其实是最直观的。其次,使用对象化的方式拼接SQL,还是有其局限性,大量的SQL文本也不宜直接写在Java类中。所以,FoxnicSQL将原本要写在Java类中的SQL语句放到一个外部文件中,每个语句用一个ID去标识,在SQL执行时,只要指定ID就可以了。在此基础上,FoxnicSQL加入了模板引擎、SQL语句置换、热加载等特性,使其变得更加好用。
小万哥 小万哥
6个月前
Python 异常处理:try、except、else 和 finally 的使用指南
异常处理当发生错误(或我们称之为异常)时,Python通常会停止执行并生成错误消息。try块用于测试一段代码是否存在错误。except块用于处理错误。else块用于在没有错误时执行代码。finally块用于无论try和except块的结果如何都要执行的代码
小万哥 小万哥
2个月前
Java 异常处理与正则表达式详解,实例演练及最佳实践
Java异常Try...Catch在Java代码执行期间,可能会发生各种错误,包括程序员编码错误、用户输入错误以及其他不可预料的状况。当错误发生时,Java通常会停止并生成错误消息,这个过程称为抛出异常。try...catch语句try语句允许您定义一段代