当然return在finally之前执行了~~~

解决方案 »

  1.   

    先执行 b=88
    然后执行  finally
    最后 return
      

  2.   


    未验证的说法:
    1、先计算返回值
    2、执行finally
    3、执行return关键在对return理解上,个人认为return应该表示返回,退出或者结束方法的意思,如果先执行,那应该先输出返回值才会执行finally而java对finally的解释也是finally总在方法结束前执行。
      

  3.   

    函数应该是栈调用,如果先执行return ,哪不是退到上个栈了,怎么调用finally, 所以我觉得先调用finally
      

  4.   

    finally当初被用来设计为处理善后工作,应该是在最后执行。
      

  5.   


      似乎这里的return只是退出 try{} 部分,并不是函数体
      

  6.   

    to jackyzgm试试下面的程序就知道return退出哪里了。public class Test22{
    public static void main(String[] args){
    System.out.print(tt());
    }
    public static int tt(){
    int b = 23;
    try{
    System.out.println("yes");
    return b=88;
    }
    catch(Exception e){
    System.out.println("error : " + e);
    }
    finally{
    b=90;
    if(b>25){
    System.out.println("b>25 : "+b);
    b=10;
    }
    System.out.println("finally");
    }                  System.out.println("test");
    return b=100;
    }
    }
      

  7.   

    可是我的结果证明了 finally 里已经 b=88 ------------------------ 回复人: nwp123(风中浮云) ( ) 信誉:100  2004-12-11 21:13:00  得分: 0  
     
     
       函数应该是栈调用,如果先执行return ,哪不是退到上个栈了,怎么调用finally, 所以我觉得先调用finally
      
     
      

  8.   

    to febchen() :我的程序写的不太好,(虽然能证明return先执行了),通过你的程序知道确实 return 后已经退出函数体,但是,也许有这样的情况:
    (1)return后即不执行后面的一般的代码
    (2)无论无何,finally还是要执行,因此,如果 finally 里有个 return 11,那么,返回值就是11
      

  9.   

    //Test.java
    public class Test {
        public static void main(String[] args){
            System.out.print(tt());
        }    public static int tt(){
            int b = 23;
            try {
                return b = 88;
            }
            finally {
                if(b > 25) {
                    System.out.println("b > 25 : " + b);
                }
            }
        }
    }//调用javap -c Test后得到的字节码序列
    Compiled from "Test.java"
    public class Test extends java.lang.Object{
    public Test();
      Code:
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
       4:   returnpublic static void main(java.lang.String[]);
      Code:
       0:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       3:   invokestatic    #3; //Method tt:()I
       6:   invokevirtual   #4; //Method java/io/PrintStream.print:(I)V
       9:   returnpublic static int tt();
      Code:
       0:   bipush  23
       2:   istore_0
       3:   bipush  88
       5:   dup
       6:   istore_0
       7:   istore_1
       8:   jsr     19
       11:  iload_1
       12:  ireturn
       13:  astore_2
       14:  jsr     19
       17:  aload_2
       18:  athrow
       19:  astore_3        // 开始执行finally子句,先把当前的返还地址出栈保存在局部变量3中
       20:  iload_0
       21:  bipush  25
       23:  if_icmple       51
       26:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       29:  new     #5; //class StringBuffer
       32:  dup
       33:  invokespecial   #6; //Method java/lang/StringBuffer."<init>":()V
       36:  ldc     #7; //String b > 25 :
       38:  invokevirtual   #8; //Method java/lang/StringBuffer.append:(Ljava/lang/S
    tring;)Ljava/lang/StringBuffer;
       41:  iload_0
       42:  invokevirtual   #9; //Method java/lang/StringBuffer.append:(I)Ljava/lang
    /StringBuffer;
       45:  invokevirtual   #10; //Method java/lang/StringBuffer.toString:()Ljava/la
    ng/String;
       48:  invokevirtual   #11; //Method java/io/PrintStream.println:(Ljava/lang/St
    ring;)V
       51:  ret     3       // finally子句结束,从局部变量3中取得返回地址
      Exception table:
       from   to  target type
         3    11    13   any
        13    17    13   any}上面的中文注释是根据《深入java虚拟机(中文版)》里18章关于finally子句的说明来写的
    因此我的理解是:
    return b = 88;其实是先执行了b = 88这个计算,并把计算结果的地址保存在一个临时的局部变量中,然后开始执行finally子句,finally执行完毕后,再从先前的临时变量中取得返回地址,返回方法的最终结果。根据这样的处理方式,可以试验,当我们试图在finally子句中再行改变b的值时,已经不会对方法的返回结果造成影响。下面是一段例程:
    // Test2.java
    public class Test2 {
        public static void main(String[] args){
            System.out.print(tt());
        }    public static int tt(){
            int b = 23;
            try {
                return b = 88;
            }
            finally {
                if(b > 25) {
                    b = 66;
                    System.out.println("b > 25 : " + b);
                }
            }
        }
    }执行结果为:
    b > 25 : 66
    88
      

  10.   

    在网吧,没JDK,其他人试一下这个程序public static void main(String args[])
    {
    System.out.println(test());
    }
    public static String test()
    {
    String temp="abc";
    System.out.println("在test()里,try之前");
    try{
    System.out.println("在try里");
    retrun temp="123";
    }
    catch(Exception e){}
    finally
    {
    System.our.println("在finally里");
    }
    System.our.println("在test()里,try之后,temp是:"+temp);
    }
      

  11.   

    to zcjl() :阁下意思是: ?(1)执行return (后面)部分的计算,确定返回结果
    (2)执行finally
    (2)执行return的退出函数的动作那么,这里的“return 语句”是指(1)还是(3)呢??  这个问题的答案就歧义了。
      

  12.   

    to zcjl() :可是,如果finally里有 return 123 ,那么,最后返回的结果就是 123,这样返回结果不也是改变了吗?这样不是也证明了 finally 仍旧是最后执行的吗?
      

  13.   

    如果你在 try中放了return
    那么在finally里就不可能再放置了return了编译器里会告诉你finally里的retrun是
    unreachable statement编译理论里很重要的就是不能有二义性,所以不会出现你说的歧异情况。其实我的程序和zcjl()的程序都说明了在finally里是不会改变返回值的可以这么理解
    这里return b实际分2次执行
    1次是计算返回值
    然后看看有无finally之类的事情要做
    然后在真正返回(退栈,或者说退出方法)
      

  14.   

    把楼主的程序改成如下的形式;
    class Test22
    {
    public static void main(String[] args)
    {
    System.out.print(tt());
    }
    public static int tt()
    {
    int b = 23;
    try
    {
    System.out.println("yes");
    return b=88;
    }
    catch(Exception e)
    {
    System.out.println("error : " + e);
    }
    finally
    {
    if(b>25)
    {
    System.out.println("b>25 : "+b);
    b=120;
    }
    else System.out.println("finally");
    }
    b=100;
    System.out.println("excute"+b);
    return b;
    }
    }
    输出的结果是:
    yes
    b>25 : 88
    88按照febchen的意思:
    未验证的说法:
    1、先计算返回值
    2、执行finally
    3、执行return关键在对return理解上,个人认为return应该表示返回,退出或者结束方法的意思,如果先执行,那应该先输出返回值才会执行finally而java对finally的解释也是finally总在方法结束前执行。tt()的返回值应该是120,怎么还是88呢?
    大家继续分析一下,看是怎么回事
      

  15.   

    刚才
    zcjl() 
    说的很清楚了
    在finally里是不会改变返回值的这样说:
    1、先计算返回值,并保留了此值(b=88,88被保存了)
    2、执行finally,此时可以改变b的值
    3、执行return,将保存的88取出并返回可以仔细看看zcjl() 贴的代码
      

  16.   

    //-------------------------------//
    如果你在 try中放了return
    那么在finally里就不可能再放置了return了编译器里会告诉你finally里的retrun是
    unreachable statement
    //-----------------------------------//可是还是可以放的啊,你看下以下代码,可以运行,虽然 编译器也说了finally代码不能正常完成,但是还能执行,输出的结果还是finally的return的返回值public class Test22 {
        public static void main(String[] args){
            System.out.print(tt());
        }    public static int tt(){
            try {
                return 1;
            }
            catch(Exception e){}
            finally {
             return 2;
            }
        }
    }
      

  17.   

    恩,是我看错了
    应该可以
    这样就返回10了一个方法只能有1个返回值把,还是应该说明finally先执行了退出方法,所以前面的return也就执行不到了。水平有限,只好就事论事了。public class Test22{
    public static void main(String[] args){
    System.out.print(tt());
    }
    public static int tt(){
    int b = 23;
    try{
    System.out.println("yes");
    return b=88;
    }
    catch(Exception e){
    System.out.println("error : " + e);
    }
    finally{
    b=90;
    if(b>25){
    System.out.println("b>25 : "+b);
    b=10;
    }
    System.out.println("finally");
    return b;
    }
    }
    }
      

  18.   

    to:  febchen() 
    如下:
    public static void main(String[] args) {
            System.out.print(tt());
        }
        public static int tt(){
                int b = 23;
                try{
                    System.out.println("yes");
                    return b=88;
                }
                catch(Exception e){
                    System.out.println("error : " + e);
                }
                finally{
                    b=90;
                    if(b>25){
                        System.out.println("b>25 : "+b);
                        b=10;
                    }
                    System.out.println("finally");
                    return b = 11;
                }
            }执行结果:yes
    b>25 : 90
    finally
    11编译器并没有报告任何问题。在try 中有 return 的情况下,finally里仍然可以写return,只是在 finally 里的 return 之后写任何代码都会报告 unreachable statement 的错误我的理解,执行顺序是这样的:首先在 try 中的 return b = 88; 时,执行了 b =88; 这句代码,然后并不返回, 而是把 88 保存在一个临时的地方,并去执行 finally 中的代码。 finally 执行完后,从取出那个临时的地方取出 88 返回。 如果在 finally中有return b = 11; 这句,则在执行到这里时,又把 11 放在了起先保存 88 的位置,这里如果再取的时候,返回结果就是11了。 不过到底这个返回值是由try里的return返回的,还是由finally里的return返回的,我还不太清楚。 我倾向于是由finally里的try返回的
      

  19.   

    //----------
    一个方法只能有1个返回值把,
    ----------------------------//返回值是一个,可是确实可以有多个 return 语句。//------------------
    还是应该说明finally先执行了退出方法,所以前面的return也就执行不到了。
    -----------------------------------------------------------------------//这个我觉得不够说服力,因为无法证明执行finally{}之前try{}里的 return 没执行过。换种说法,也可以这样理解啊, finally{}里的 return 改变了 返回值。
      

  20.   

    try {
        return 1;  //1处
    } catch (Exception e) {
        return 2;
    } finally {
        return 3;  //2处
    }执行结果返回的是 3
    但是这个 3 是由 1处 返回的,还是由 2处 返回的? 我不知道了。你告诉我吧。 呵呵
      

  21.   

    没有说前面的return没有被执行,只是计算了返回值,并没有退出如下程序,return b=88还是起作用的。public class Test22{
    public static void main(String[] args){
    System.out.print(tt());
    }
    public static int tt(){
    int b = 23;
    try{
    System.out.println("yes");
    return b=88;
    }
    catch(Exception e){
    System.out.println("error : " + e);
    }
    finally{
    if(b>25){
    System.out.println("b>25 : "+b);
    b=10;
    }
    System.out.println("finally");
    return b;
    }
    }
    }我觉得你认为所谓执行return,就是执行return b=88这条语句,而题目中说的finally在return前运行,这里的return是说退出方法,所以产生如此争论,其实大家都没有错误,只是理解角度问题此外,好像C#中就不允许在finally中写return了。
      

  22.   

    管它什么答案呢, 弄清楚是怎么执行的就行了,不过我的问题谁回答一下try {
        return 1;  //1处
    } catch (Exception e) {
        return 2;
    } finally {
        return 3;  //2处
    }执行结果返回的是 3
    但是这个 3 是由 1处 返回的,还是由 2处 返回的? 我不知道了。你告诉我吧。 呵呵
      

  23.   

    你用这个看吧
    javap -c Test22   0 bipush 20
       2 istore_0
       3 iconst_1
       4 dup
       5 istore_0
       6 istore_1
       7 jsr 28
      10 iload_1
      11 ireturn
      12 astore_1
      13 iconst_2
      14 dup
      15 istore_0
      16 istore_2
      17 jsr 28
      20 iload_2
      21 ireturn
      22 astore_3
      23 jsr 28
      26 aload_3
      27 athrow
      28 astore 4
      30 iconst_3
      31 dup
      32 istore_0
      33 ireturn我的理解是:无论怎样执行,都会跳到28(jsr 28)
    即finally执行的地方,这里通过astore 4保存返回地址,如果finally中没有return就会是象zcjl() 说得通过ret 4调用1处的return,否则调用2处的return了
      

  24.   

    有些晕了,我到觉得,如果一个方法退出了,那么里面的语句就不会被执行到了。至于return b=88之类,在没有finally的情况下确实就是结束了,有了finally,就会先做好退出准备,然后等finally结束后在进行下去。不能写了,回家睡觉了。
      

  25.   

    首先,自己写程序不会象上面那样写的,了解这个问题对写程序没什么意思。如果就技术层面上讨论这个问题的话,我还是比较认同上面几位分析java pcode的同学。如果没有研究到java 编译或pcode这个深度,讨论这个问题就没什么意思了。
      

  26.   

    知道方法的调用过程,调用前JVM的状态保存在栈中,返回后将恢复保存的状态,就不可能在执行FINALLY里的代码了,先b=88后finally,再return
      

  27.   


      讨论到这里,我应该已经明白了,返回值和return是两码事,最终return还是最后执行,如果这个函数为void的话,那么我们就不用考虑返回值了。 return就是退出函数的意思了。  多谢各位的讨论,问题已经弄明白,网上流传的答案是正确的。 return 最后执行退出函数动作。
      

  28.   

    不好意思,昨天有事出去了,没能及时回复楼主后面的疑问
    我把我的理解写到了blog中,http://blog.csdn.net/zcjl/archive/2004/12/12/214123.aspx
    有不当之处,还望指正