大家讨论一下finally 和 try里的 return 的先后问题,我看了很多答案都错误 当然return在finally之前执行了~~~ 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 先执行 b=88然后执行 finally最后 return 未验证的说法:1、先计算返回值2、执行finally3、执行return关键在对return理解上,个人认为return应该表示返回,退出或者结束方法的意思,如果先执行,那应该先输出返回值才会执行finally而java对finally的解释也是finally总在方法结束前执行。 函数应该是栈调用,如果先执行return ,哪不是退到上个栈了,怎么调用finally, 所以我觉得先调用finally finally当初被用来设计为处理善后工作,应该是在最后执行。 似乎这里的return只是退出 try{} 部分,并不是函数体 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; }} 可是我的结果证明了 finally 里已经 b=88 ------------------------ 回复人: nwp123(风中浮云) ( ) 信誉:100 2004-12-11 21:13:00 得分: 0 函数应该是栈调用,如果先执行return ,哪不是退到上个栈了,怎么调用finally, 所以我觉得先调用finally to febchen() :我的程序写的不太好,(虽然能证明return先执行了),通过你的程序知道确实 return 后已经退出函数体,但是,也许有这样的情况:(1)return后即不执行后面的一般的代码(2)无论无何,finally还是要执行,因此,如果 finally 里有个 return 11,那么,返回值就是11 //Test.javapublic 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/String;)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/lang/String; 48: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)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.javapublic 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 : 6688 在网吧,没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);} to zcjl() :阁下意思是: ?(1)执行return (后面)部分的计算,确定返回结果(2)执行finally(2)执行return的退出函数的动作那么,这里的“return 语句”是指(1)还是(3)呢?? 这个问题的答案就歧义了。 to zcjl() :可是,如果finally里有 return 123 ,那么,最后返回的结果就是 123,这样返回结果不也是改变了吗?这样不是也证明了 finally 仍旧是最后执行的吗? 如果你在 try中放了return那么在finally里就不可能再放置了return了编译器里会告诉你finally里的retrun是unreachable statement编译理论里很重要的就是不能有二义性,所以不会出现你说的歧异情况。其实我的程序和zcjl()的程序都说明了在finally里是不会改变返回值的可以这么理解这里return b实际分2次执行1次是计算返回值然后看看有无finally之类的事情要做然后在真正返回(退栈,或者说退出方法) 把楼主的程序改成如下的形式;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; }}输出的结果是:yesb>25 : 8888按照febchen的意思:未验证的说法:1、先计算返回值2、执行finally3、执行return关键在对return理解上,个人认为return应该表示返回,退出或者结束方法的意思,如果先执行,那应该先输出返回值才会执行finally而java对finally的解释也是finally总在方法结束前执行。tt()的返回值应该是120,怎么还是88呢?大家继续分析一下,看是怎么回事 刚才zcjl() 说的很清楚了在finally里是不会改变返回值的这样说:1、先计算返回值,并保留了此值(b=88,88被保存了)2、执行finally,此时可以改变b的值3、执行return,将保存的88取出并返回可以仔细看看zcjl() 贴的代码 //-------------------------------//如果你在 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; } }} 恩,是我看错了应该可以这样就返回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; } }} 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; } }执行结果:yesb>25 : 90finally11编译器并没有报告任何问题。在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返回的 //----------一个方法只能有1个返回值把,----------------------------//返回值是一个,可是确实可以有多个 return 语句。//------------------还是应该说明finally先执行了退出方法,所以前面的return也就执行不到了。-----------------------------------------------------------------------//这个我觉得不够说服力,因为无法证明执行finally{}之前try{}里的 return 没执行过。换种说法,也可以这样理解啊, finally{}里的 return 改变了 返回值。 try { return 1; //1处} catch (Exception e) { return 2;} finally { return 3; //2处}执行结果返回的是 3但是这个 3 是由 1处 返回的,还是由 2处 返回的? 我不知道了。你告诉我吧。 呵呵 没有说前面的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了。 管它什么答案呢, 弄清楚是怎么执行的就行了,不过我的问题谁回答一下try { return 1; //1处} catch (Exception e) { return 2;} finally { return 3; //2处}执行结果返回的是 3但是这个 3 是由 1处 返回的,还是由 2处 返回的? 我不知道了。你告诉我吧。 呵呵 你用这个看吧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了 有些晕了,我到觉得,如果一个方法退出了,那么里面的语句就不会被执行到了。至于return b=88之类,在没有finally的情况下确实就是结束了,有了finally,就会先做好退出准备,然后等finally结束后在进行下去。不能写了,回家睡觉了。 首先,自己写程序不会象上面那样写的,了解这个问题对写程序没什么意思。如果就技术层面上讨论这个问题的话,我还是比较认同上面几位分析java pcode的同学。如果没有研究到java 编译或pcode这个深度,讨论这个问题就没什么意思了。 知道方法的调用过程,调用前JVM的状态保存在栈中,返回后将恢复保存的状态,就不可能在执行FINALLY里的代码了,先b=88后finally,再return 讨论到这里,我应该已经明白了,返回值和return是两码事,最终return还是最后执行,如果这个函数为void的话,那么我们就不用考虑返回值了。 return就是退出函数的意思了。 多谢各位的讨论,问题已经弄明白,网上流传的答案是正确的。 return 最后执行退出函数动作。 不好意思,昨天有事出去了,没能及时回复楼主后面的疑问我把我的理解写到了blog中,http://blog.csdn.net/zcjl/archive/2004/12/12/214123.aspx有不当之处,还望指正 哪位大侠能给出用java做一个音乐播放器的具体方法啊? twitter4j 请问怎样在一个类中叠代LIST的内容?3Q. 关于Scanner,它有内置的缓冲区吗?有什么其它的好处 instanceof是哪个类里定义的。 请帮忙修改代码!(有关多线程) 华为招聘 不懂;以每两个字节为单位对字符串进行处理。这两个字节直接转化为数字就是&#xxxxx;中的xxxxx,如果这个数字小于128就直接使用这个字符( java初学者求助!! 新人求助, 一个java的基础问题 在JPanel中生成JDialog并弹出的问题 幫忙看看這樣簡單的錯誤 :ClassNotFoundException 在線等後
然后执行 finally
最后 return
未验证的说法:
1、先计算返回值
2、执行finally
3、执行return关键在对return理解上,个人认为return应该表示返回,退出或者结束方法的意思,如果先执行,那应该先输出返回值才会执行finally而java对finally的解释也是finally总在方法结束前执行。
似乎这里的return只是退出 try{} 部分,并不是函数体
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;
}
}
函数应该是栈调用,如果先执行return ,哪不是退到上个栈了,怎么调用finally, 所以我觉得先调用finally
(1)return后即不执行后面的一般的代码
(2)无论无何,finally还是要执行,因此,如果 finally 里有个 return 11,那么,返回值就是11
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
{
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);
}
(2)执行finally
(2)执行return的退出函数的动作那么,这里的“return 语句”是指(1)还是(3)呢?? 这个问题的答案就歧义了。
那么在finally里就不可能再放置了return了编译器里会告诉你finally里的retrun是
unreachable statement编译理论里很重要的就是不能有二义性,所以不会出现你说的歧异情况。其实我的程序和zcjl()的程序都说明了在finally里是不会改变返回值的可以这么理解
这里return b实际分2次执行
1次是计算返回值
然后看看有无finally之类的事情要做
然后在真正返回(退栈,或者说退出方法)
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呢?
大家继续分析一下,看是怎么回事
zcjl()
说的很清楚了
在finally里是不会改变返回值的这样说:
1、先计算返回值,并保留了此值(b=88,88被保存了)
2、执行finally,此时可以改变b的值
3、执行return,将保存的88取出并返回可以仔细看看zcjl() 贴的代码
如果你在 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;
}
}
}
应该可以
这样就返回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;
}
}
}
如下:
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返回的
一个方法只能有1个返回值把,
----------------------------//返回值是一个,可是确实可以有多个 return 语句。//------------------
还是应该说明finally先执行了退出方法,所以前面的return也就执行不到了。
-----------------------------------------------------------------------//这个我觉得不够说服力,因为无法证明执行finally{}之前try{}里的 return 没执行过。换种说法,也可以这样理解啊, finally{}里的 return 改变了 返回值。
return 1; //1处
} catch (Exception e) {
return 2;
} finally {
return 3; //2处
}执行结果返回的是 3
但是这个 3 是由 1处 返回的,还是由 2处 返回的? 我不知道了。你告诉我吧。 呵呵
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了。
return 1; //1处
} catch (Exception e) {
return 2;
} finally {
return 3; //2处
}执行结果返回的是 3
但是这个 3 是由 1处 返回的,还是由 2处 返回的? 我不知道了。你告诉我吧。 呵呵
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了
讨论到这里,我应该已经明白了,返回值和return是两码事,最终return还是最后执行,如果这个函数为void的话,那么我们就不用考虑返回值了。 return就是退出函数的意思了。 多谢各位的讨论,问题已经弄明白,网上流传的答案是正确的。 return 最后执行退出函数动作。
我把我的理解写到了blog中,http://blog.csdn.net/zcjl/archive/2004/12/12/214123.aspx
有不当之处,还望指正