关于trycatchfinal返回值问题

来源:互联网 发布:打条码软件 编辑:程序博客网 时间:2024/06/06 00:01

关于try...catch...finally中return的疑惑

关于try...catch...finally里面的return一直是面试的一个热门考点。无非就分以下几个情况:

1、当有finally语句并且try中有return,在执行到return(还未执行)的时候,会先执行finally里面的内容,然后再执行行try中的return。

复制代码
package com.and.java.demo;public class 测试 {    public static void main(String[] args) {        System.out.println(new 测试().test());    }    public String test() {        try {            System.out.println("try{...}");            return "try";        } catch (Exception e) {            System.out.println("catch{...}");            return "catch";        } finally {            System.out.println("finally{...}");        }    }}
复制代码

输出:

try{...}finally{...}try

2、在1的基础上,如果finally里面也有return语句,则try代码块中的return被屏蔽(不执行),即在try中遇到return的时候,会先执行finally里面的内容(包括finally里面的return语句)。

复制代码
package com.and.java.demo;public class 测试 {    public static void main(String[] args) {        System.out.println(new 测试().test());    }    public String test() {        try {            System.out.println("try{...}");            return "try";        } catch (Exception e) {            System.out.println("catch{...}");            return "catch";        } finally {            System.out.println("finally{...}");            return "finally";        }    }}
复制代码

输出:

try{...}finally{...}finally

遇到的问题:

这两种情况想必大家已经掌握。但是还有一种情况,也是我不能理解的地方。一般情况下,在finally里面作一些数据的关闭操作(比如文件,输入/输出流,数据库的关闭),试想一下,要是我们在finally里面对要返回的值进行修改,那会反应到最终的结果上去吗?(因为从上面的讲解可以知道,当try里面有return的时候,它不会立刻执行,会先执行finally里面的内容,然后再执行return)。

复制代码
package com.and.java.demo;public class 测试 {    public static void main(String[] args) {        System.out.println(new 测试().test());    }    public String test() {        String result = "";        try {            result = "try";            return result;        } catch (Exception e) {            result = "catch";            return result;        } finally {            result = "finally";        }    }}
复制代码

试想一下,它会输出"try" 呢还是"finally"呢?

输出:

try

确实只输出try,但是我们在finally里面是改变了result的值呀?
再进一步改进,判断finally里面的赋值语句是否执行

复制代码
package com.and.java.demo;public class 测试 {    public static void main(String[] args) {        System.out.println(new 测试().test());    }    public String test() {        String result = "";        try {            result = "try";            return result;        } catch (Exception e) {            result = "catch";            return result;        } finally {            System.out.println("t1->"+result);            result = "finally";            System.out.println("t2->"+result);        }    }}
复制代码

输出:

t1->tryt2->finallytry

从输出结果可以看出,finally里面的赋值语句是执行了的,但是在return结果中怎么就没变呢?(目前暂时研究到这个地步,仍没搞明白,还望各位高手指点)

标签: java, try, catch, finally, return

好文要顶 关注我 收藏该文  
And.He
关注 - 4
粉丝 - 117 
+加关注
0
0
« 上一篇:模仿网易新闻客户端(RSS版)(二)
» 下一篇:iOS学习笔记之NSString
posted @ 2012-04-17 15:15 And.He 阅读(5242) 评论(12) 编辑 收藏

  
#1楼 2012-04-17 16:55 LAO年糕  
楼主如果记住String是引用类型就很好理解了,例如”try“的地址这里为0x001、“finally”的地址为0x002,在try中return 的result指向的是“try”的地址0x001,所以return的时候返回的也应该是“try“的地址0x001;而在finally中将变量result指向地址修改为0x002 ,但没有使用return返回新的地址,所有在调用入口处得到的指向任然是0x001所以在mai中输出的时候是去0x001取值而不是去0x002取;
这是我的理解,或许存在误解欢迎指点。。。(*^__^*) 嘻嘻
支持(0)反对(0)
  
#2楼[楼主2012-04-17 21:48 And.He  
欢迎你参与回复,我试过了,与String无关,把String改成int类型也一样,目前我的猜想就是,在try中遇到return的时候,虽然没有立即把当前的值返回出去,但是这个值已经在了,而在finally中,改变了这个值,不影响当前函数的返回值。不知道我表述清楚没有。如果把要返回的值定义在函数外面(全局),可以通过输出查看,最后它的值还是改变了的。只是在try中遇到return的时候,暂时把要返回的值取出来放那儿的,执行完finally后再返回。目前我是这样理解的。欢迎指正
支持(0)反对(0)
  
#3楼 2012-04-17 22:53 cavlary  
@ And.He
int 也属于值引用的,try,catch,finally是三个不用的作用域,执行try里面的result = "try",然后执行finally里面的result = "finally",其实这个时候try里面的result的值并没有改变,它只是将它的值copy给到了finally,是里面的一个临时变量而已,所以finally里的操作对try里面的值没有改变的,而执行完finally里的操作后,finally里的result就被丢弃了,等着回收
支持(0)反对(0)
  
#4楼[楼主2012-04-17 23:03 And.He  
你的最后一句我不赞同,再看下面代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class 测试 {
    int i = 0;
    public static void main(String[] args) {
        测试 t = new 测试();
        System.out.println(t.i);
        System.out.println(t.test());
        System.out.println(t.i);
    }
 
    public int test() {
        try {
            i = 1;
            return i;
        catch (Exception e) {
            i = -1;
            return i;
        finally {
            i = 2;
        }
    }
}
支持(0)反对(0)
  
#5楼 2012-04-18 11:53 bevin-H  
是不是和result的作用域有关?我是菜鸟,恳请指正。
支持(0)反对(0)
  
#6楼 2012-04-18 17:55 houjinxin  
这个问题好复杂,我也想不出合理的解释,这个可能跟底层的一些东西有关吧
支持(0)反对(0)
  
#7楼 2012-04-18 18:41 houjinxin  
我又研究了一下,发现在finally块中被执行的代码,只有在return的时候才会覆盖try中的结果,换句话说,虽然在finally中改变了result的值,但是并没有被返回,在try,finnaly里都可以返回结果,而finnaly中的返回值会覆盖try中的返回值,既然finnaly中没有返回值,又何来覆盖一说呢!!
支持(0)反对(0)
  
#8楼 2012-04-18 18:43 houjinxin  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class 测试 {
    public static void main(String[] args) {
        System.out.println(new 测试().test());
    }
 
    public String test() {
        String result = "";
        try {
            result = "try";
            return result;
        catch (Exception e) {
            result = "catch";
            return result;
        finally {
            System.out.println("t1->"+result);
            result = "finally";
            System.out.println("t2->"+result);
           //在这里加上一行,就会看到返回值变了
         return result;
        }
    }
}
支持(0)反对(0)
  
#9楼 2012-04-18 23:03 God Is Coder  

try{
s ="a";
return s;
}catch{
s="b";
return s;
}finally{
s ="c";
}
结构中虚拟机的处理方式是 在try 语句中 会把return的变量引用的对象存入一个局部变量表(虚拟机可见,程序不可见)里面,然后进入finally语句块中,如果finally没有return语句,则处理finally的语句,这个时候finally的变量S和Try中的变量S是同一个变量,所以S的值是改变的。但是finally执行结束之后,return 返回值的时候,会把复制的结果返回

例如下面的代码
public class TryCatchFinally {

@SuppressWarnings("finally")
public Test test() {
Test t = new Test();

try {
t.setS("try");

return t;
} catch (Exception e) {
//result = "catch";
return t;
} finally {
t = new Test();
t.setS("finallyu");
//return result;

}
}

}


class Test{
public String s ="a";
public void setS(String s){
this.s = s;
}
}

其实还是返回的 Test.getS() 结果为 try
支持(0)反对(0)
  
#10楼[楼主2012-04-19 08:32 And.He  
谢谢大家的热心回答
支持(0)反对(0)
  
#11楼 2015-05-06 11:22 ChuckLu  
你这个针对哪一个编程语言的?
C#的finally里面,不允许return的
支持(0)反对(0)
  
#12楼 2017-03-01 17:21 博客管家  
我知道为什么了。博主所说的,try代码块中的return被屏蔽(不执行),是错误的,不会被屏蔽,仍然执行,屏蔽的仅仅是跳转指令。
package com.and.java.demo;

public class 测试 {
public static void main(String[] args) {
System.out.println(new 测试().test());
}

public String test() {
try {
System.out.println("try{...}");
return "try";
} catch (Exception e) {
System.out.println("catch{...}");
return "catch";
} finally {
System.out.println("finally{...}");
return "finally";
}
}
}
分析以上代码,先执行try中的return语句,该语句会将"try"对象的引用保存到CPU的寄存器中,该语句的跳转指令被屏蔽。然后执行finally中的return语句,该语句会将“finally”对象的引用保存到CPU的寄存器中(覆盖了try的),然后执行跳转指令。所以返回的是指向"finally"的指针,但是try中的return的确执行了。
package com.and.java.demo;

public class 测试 {
public static void main(String[] args) {
System.out.println(new 测试().test());
}

public String test() {
String result = "";
try {
result = "try";
return result;
} catch (Exception e) {
result = "catch";
return result;
} finally {
result = "finally";
}
}
}
分析以上代码,先执行try中的return语句(try中的语句总是先执行),该语句会将"try"对象的引用保存到CPU的寄存器中,然后执行finllay语句,该语句会将result局部变量的值重新定位成指向"finally"对象。最后执行跳转指令,因为CPU寄存器中保存的是“try”的引用,所以返回值是"try"的引用。
支持(0)反对(0)
刷新评论刷新页面返回顶部
最新IT新闻:
· Windows 10周年更新迎神秘累积更新:还是没有更新日志
· OpenSSL团队成员将于9月拜访中国:经过上海/深圳/北京三地
· Uber新CEO致老东家公开信:与你们共事是我的荣幸
· Google地图想要帮助用户在25个新城市找到停车位
· NASA将在明年上半年发射InSight火星探测器
» 更多新闻...
最新知识库文章:
· 做到这一点,你也可以成为优秀的程序员
· 写给立志做码农的大学生
· 架构腐化之谜
· 学会思考,而不只是编程
· 编写Shell脚本的最佳实践
» 更多知识库文章...


关闭
 

有return的情况下try catch finally的执行顺序(最有说服力的总结)

标签: 编译器stringclass测试
 134056人阅读 评论(28) 收藏 举报
 分类:


结论:
1、不管有木有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
举例:
情况1:try{} catch(){}finally{} return;
            显然程序按顺序执行。
情况2:try{ return; }catch(){} finally{} return;
          程序执行try块中return之前(包括return语句中的表达式运算)代码;
         再执行finally块,最后执行try中return;
         finally块之后的语句return,因为程序在try中已经return所以不再执行。
情况3:try{ } catch(){return;} finally{} return;
         程序先执行try,如果遇到异常执行catch块,
         有异常:则执行catch中return之前(包括return语句中的表达式运算)代码,再执行finally语句中全部代码,
                     最后执行catch块中return. finally之后也就是4处的代码不再执行。
         无异常:执行完try再finally再return.
情况4:try{ return; }catch(){} finally{return;}
          程序执行try块中return之前(包括return语句中的表达式运算)代码;
          再执行finally块,因为finally块中有return所以提前退出。
情况5:try{} catch(){return;}finally{return;}
          程序执行catch块中return之前(包括return语句中的表达式运算)代码;
          再执行finally块,因为finally块中有return所以提前退出。
情况6:try{ return;}catch(){return;} finally{return;}
          程序执行try块中return之前(包括return语句中的表达式运算)代码;
          有异常:执行catch块中return之前(包括return语句中的表达式运算)代码;
                       则再执行finally块,因为finally块中有return所以提前退出。
          无异常:则再执行finally块,因为finally块中有return所以提前退出。

最终结论:任何执行try 或者catch中的return语句之前,都会先执行finally语句,如果finally存在的话。
                  如果finally中有return语句,那么程序就return了,所以finally中的return是一定会被return的,
                  编译器把finally中的return实现为一个warning。

 

下面是个测试程序public class FinallyTest  {public static void main(String[] args) { System.out.println(new FinallyTest().test());;}static int test(){int x = 1;try{x++;return x;}finally{++x;}}}结果是2。
分析:
在try语句中,在执行return语句时,要返回的结果已经准备好了,就在此时,程序转到finally执行了。在转去之前,try中先把要返回的结果存放到不同于x的局部变量中去,执行完finally之后,在从中取出返回结果,因此,即使finally中对变量x进行了改变,但是不会影响返回结果。它应该使用栈保存返回值。

61
 
1
 
 

  相关文章推荐
  •  有return的情况下try catch finally的执行顺序(最有说服力的总结)
  •  【直播】大中型UGC信息网站SEO分享--乔向阳
  •  try_catch_finally异常处理java
  •  【直播】打通Linux脉络 进程、线程和调度--宋宝华
  •  使用try-catch-finally处理异常
  •  【直播】Java最佳学习路线指导--肖海鹏
  •  Stress Testing压力测试(Stress Testing)是指模拟巨大的工作负荷以查看应用程序在峰值使用情况下如何执行操作
  •  【套餐】C++音视频实战技术套餐--夏曹俊
  •  try 与 catch finally关键字
  •  【套餐】0基础拿下HTML5和CSS3--李仁密
  •  java try…catch…finally捕获异常的实例
  •  【套餐】机器学习之数学基础系列--AI100
  •  Java中finally块执行与return关系深度剖析
  •  java try…catch嵌套捕获异常的实例
  •  Try Catch对效能的影响测试
  •  java 中finally语句块与return的执行关系
查看评论
19楼 落叶伤剑2017-04-13 19:06发表 [回复]
如果finally中没有return语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别,分以下两种情况,:

1)如果return的数据是基本数据类型或文本字符串,则在finally中对该基本数据的改变不起作用,try中的return语句依然会返回进入finally块之前保留的值。

2)如果return的数据是引用数据类型,而在finally中对该引用数据类型的属性值的改变起作用,try中的return语句返回的就是在finally中改变后的该属性的值。
Re: sinat_382681592017-06-08 20:22发表 [回复]
回复落叶伤剑:谢谢层主!
18楼 飘零雁2016-12-14 10:53发表 [回复]
catch 中有throw 的话,finally不会执行
Re: 口袋本人前天 14:31发表 [回复]
回复飘零雁:会执行的,建议你去实践一下。
17楼 baidu_351455222016-10-17 10:28发表 [回复]
针对第一点,如果catch块中有System.exit(0);那么finally块是不会执行的。try块中同样。
16楼 蜿蜒2016-08-21 10:42发表 [回复]
博主语意矛盾,给人以误解吧,先....之前,再.....,到底谁先谁后?
15楼 huangpingfeng2016-04-22 11:52发表 [回复]
try{ throw e; return;}catch(){throw e} finally{return;}
这种情况,执行了finally的return后,异常也是抛不出来
14楼 huangpingfeng2016-04-22 11:51发表 [回复]
try{ throw e; return;}catch(){throw e} finally{return;}
这种情况,执行了finally的return后,异常也是抛不出来
13楼 丶封刀看海2016-04-10 22:24发表 [回复]
学习了
12楼 thewindkee2016-03-07 21:57发表 [回复]
因为使用栈保存返回值,即使finally中执行i++,但是影响不到之前保存下来的具体的值。 所以return影响不了基本型的值。
而修改list ,map,自定义类等引用类型时,虽然进入finally之前保存了引用的地址,所以在finally中引用地址指向的内容改变了, 影响了返回值。
11楼 wangqiang54172016-03-06 01:33发表 [回复]
从SEH角度分析更容易理解
10楼 飞碟说2016-01-26 09:52发表 [回复]
逻辑清晰,浅显易懂,亲测之后果然如此,谢谢楼主。
9楼 -琥珀川-2015-08-26 14:36发表 [回复]
:try{ return;}catch(){return;} finally{return;}
程序执行try块中return之前(包括return语句中的表达式运算)代码;
有异常:执行catch块中return之前(包括return语句中的表达式运算)代码;
则再执行finally块,因为finally块中有return所以提前退出。
无异常:则再执行finally块,因为finally块中有return所以提前退出。

finally中有return会吃掉异常的
Re: wxb7745678762016-03-09 08:37发表 [回复]
回复最后一句话确实经典,一语惊醒。:
Re: 青蛙的世界2016-02-14 20:10发表 [回复]
回复-琥珀川-:大兄弟啊有个问题一直没搞懂你这最后一句话救了我的命啊
8楼 风雨常乐2015-05-08 09:39发表 [回复]
谢谢楼主
7楼 zspmaomao2014-11-25 10:05发表 [回复]
1.影响返回结果的前提是在 非 finally 语句块中有 return 且非基本类型
2.不影响返回结果 的前提是 非 finally 块中有return 且为基本类型

这也解释了,为什么Date类型是被修改的,究其本质 基本类型在栈中存储,返回的是真实的值,而引用类型返回的是其浅拷贝堆地址.所以才会改变~
6楼 浪羽清风2014-11-06 18:01发表 [回复]
引用“wangq2110”的评论:测试demo
[code=csharp]
static void Main(string[] ar...

基本数据类型是不能修改的,其他的可以修改,包括date
Re: wangq21102014-11-14 13:32发表 [回复]
回复浪羽清风:听不懂你在说啥!惜字如金啊!我只希望有人给出原因,而不是结论。
5楼 wangq21102014-10-24 16:02发表 [回复]
测试demo
[csharp] view plain copy
  1. static void Main(string[] args)  
  2.        {  
  3.          /*测试test1*/   
  4.            List<string>relist=test1();  
  5.            foreach (var item in relist)  
  6.            {  
  7.                Console.WriteLine(item);  
  8.            }  
  9.            Console.ReadLine();  
  10.        }  
  11.        private static List<string> test1()  
  12.        {  
  13.            List<string> strlist = new List<string>();  
  14.            strlist.Add("zs");  
  15.            strlist.Add("ls");  
  16.            strlist.Add("ww");  
  17.            strlist.Add("mz");  
  18.            try  
  19.            {  
  20.                strlist.Add("wq");  
  21.                return strlist;  
  22.            }  
  23.            finally  
  24.            {  
  25.                strlist.Add("yyy");  
  26.            }  
  27.        }  

测试输出结果:
zs
ls
ww
mz
wq
yyy
4楼 wangq21102014-10-24 15:57发表 [回复]
楼主,求真相。求解释。共同学习。
3楼 wangq21102014-10-24 15:55发表 [回复]
引用“pairsfish”的评论:楼主之写的有些片面,得出的结论是不正确的。finally修改的基本类型是不影响返回结果的。
修改li...

我也测试了,是你说的这样,是不是和return,finally的执行顺序无关,是不是值类型和引用类型搞的鬼。郁闷!
2楼 pairsfish2014-09-19 17:16发表 [回复]
楼主之写的有些片面,得出的结论是不正确的。finally修改的基本类型是不影响返回结果的。
修改list ,map,自定义类等引用类型时,是影响返回结果 的。
但是date类型经过测试是不影响的。有点奇怪。
Re: Marksinoberg2017-03-08 21:07发表 [回复]
回复pairsfish:date类型底层貌似是对long类型的数据的封装,也就是说JVM可能在编译的时候指定了一个常量值保存了起来,所以在finally块中修改的其实不是date底层所指向的那个副本,而是对类似于基本数据类型的修改,所以返回的结果仍然是一开始编译好的时候指定的副本。也就是没变的原因。

而其他的对象(引用类型)则是被finally块中的代码改变了所引用变量的真实数据,所以发生了改变。

也就是说,严格来讲,Date类型是个伪对象类型。

以上均为个人观点,如果有误,还望指出,大家一起研究。 :)
Re: lingzhm2015-08-19 16:29发表 [回复]
回复pairsfish:我试过了,果然如你所说。。。。真奇怪了。。。
Re: VirgoSoy2015-09-12 14:52发表 [回复]
回复lingzhm::本人新手,以下是自己的观点。。感觉与参数传值或传址类似。前几天才知道java全部都是传值的,即使是对象也是传递其地址的副本。return的若是对象,则先把对象的副本保存起来,也就是说保存的是指向对象的地址。若对原来的对象进行修改。对象的地址仍然不变,return的副本仍然是指向这个对象,所用finally中对对象的修改仍然有作用。而基本数据类型保存的是原原本本的数据,return保存副本后,在finally中修改都是修改原来的数据。副本中的数据还是不变,所以finally中修改对return无影响。。
Re: Marksinoberg2017-03-08 20:57发表 [回复]
回复VirgoSoy:我觉得你总结的很好,很有道理。Java关于方法返回值应该就是对这个引用(或者基本数据)而操作的。
1楼 Optimistic_2014-09-16 08:35发表 [回复]
学习了……
发表评论
  • 用 户 名:
  • zhoulovelian
  • 评论内容:
  • 插入代码
      
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
     
    kavensu
     
    • 访问:620521次
    • 积分:4873
    • 等级:  
    • 排名:第5919名
    • 原创:39篇
    • 转载:108篇
    • 译文:4篇
    • 评论:103条
    友情链接
    Parse 
    Strikingly(傻瓜式网页设计)
    文章分类
  • Android(45)
  • Android 数据存储(2)
  • Android 自定义UI控件(6)
  • Android 进程与线程(2)
  • Android 多媒体(3)
  • Android 编程规范(2)
  • PHP(1)
  • Java(19)
  • Web 开发(4)
  • 随笔(3)
  • 创业(1)
  • 软件安装及配置(9)
  • 有启发的时文(5)
  • 算法(9)
  • 计算机网络(9)
  • Epub(3)
  • 其他(6)
  • 操作系统(3)
  • 编译原理(1)
  • UML(1)
  • 笔试面试题(6)
  • C#开发(3)
  • JavaScrip & Node.js(5)
  • Git(1)
    文章存档
  • 2016年05月(1)
  • 2016年04月(1)
  • 2015年01月(1)
  • 2014年01月(10)
  • 2013年11月(1)
  • 展开
    阅读排行
  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)(133862)
  • 邮件协议POP3/IMAP/SMTP服务的区别(57078)
  • 【使用线程池的好处】多线程的环境中,尽量采用线程池(25782)
  • TableLayout和TableRow的使用(18333)
  • C#中SQL语句的参数写法(17579)
  • 使用HttpClient通过POST方式发送XML,使用TCP/IP Monitor观察数据(16685)
  • javascript 对象数组排序(15445)
  • node.js常用模块(15132)
  • onContextItemSelected 与 onMenuItemSelected 的那些事(14486)
  • OSI的七层模型,网线,网卡,集线器,交换机,路由器分别工作在七层模型中的哪一层?(13713)
    评论排行
  • 2013网易技术类笔试题(java开发方向+移动平台开发)(30)
  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)(28)
  • onContextItemSelected 与 onMenuItemSelected 的那些事(6)
  • 使用ActivityGroup时,在Activity中显示对话框出现的问题(5)
  • 条码扫描二维码扫描——ZXing android(4)
  • 网页分页数据抓取的几种方式(3)
  • 网上下载图片并保持到SD卡中+读取SD卡中的图片(2)
  • 【使用线程池的好处】多线程的环境中,尽量采用线程池(2)
  • Android中Fragment的应用(android官方教程完美翻译)(2)
  • 用点画分隔线(2)
    推荐文章
    • * CSDN日报20170828——《4个方法快速打造你的阅读清单》
    • * CSDN博客模板调查问卷
    • * 秒杀系统的一点思考
    • * TCP网络通讯如何解决分包粘包问题
    • * 技术与技术人员的价值
    • * GitChat·人工智能 | 除了深度学习,机器翻译还需要啥?
    最新评论
  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    口袋本人: @mochounv:会执行的,建议你去实践一下。

  • 【使用线程池的好处】多线程的环境中,尽量采用线程池

    weixin_38310495: 666

  • 【使用线程池的好处】多线程的环境中,尽量采用线程池

    health7788: 厉害了

  • 2013网易技术类笔试题(java开发方向+移动平台开发)

    针叶: 感觉大公司的笔试面试就是另一种方式的计算机考研。

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    sinat_38268159: @aliangshuang:谢谢层主!

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    落叶伤剑: 如果finally中没有return语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别...

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    Marksinoberg: @pairsfish:date类型底层貌似是对long类型的数据的封装,也就是说JVM可能在编译的时...

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    Marksinoberg: @VirgoSoy:我觉得你总结的很好,很有道理。Java关于方法返回值应该就是对这个引用(或者基本...

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    飘零雁: catch 中有throw 的话,finally不会执行

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    baidu_35145522: 针对第一点,如果catch块中有System.exit(0);那么finally块是不会执行的。tr...


关闭
 

有return的情况下try catch finally的执行顺序(最有说服力的总结)

标签: 编译器stringclass测试
 134056人阅读 评论(28) 收藏 举报
 分类:


结论:
1、不管有木有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
举例:
情况1:try{} catch(){}finally{} return;
            显然程序按顺序执行。
情况2:try{ return; }catch(){} finally{} return;
          程序执行try块中return之前(包括return语句中的表达式运算)代码;
         再执行finally块,最后执行try中return;
         finally块之后的语句return,因为程序在try中已经return所以不再执行。
情况3:try{ } catch(){return;} finally{} return;
         程序先执行try,如果遇到异常执行catch块,
         有异常:则执行catch中return之前(包括return语句中的表达式运算)代码,再执行finally语句中全部代码,
                     最后执行catch块中return. finally之后也就是4处的代码不再执行。
         无异常:执行完try再finally再return.
情况4:try{ return; }catch(){} finally{return;}
          程序执行try块中return之前(包括return语句中的表达式运算)代码;
          再执行finally块,因为finally块中有return所以提前退出。
情况5:try{} catch(){return;}finally{return;}
          程序执行catch块中return之前(包括return语句中的表达式运算)代码;
          再执行finally块,因为finally块中有return所以提前退出。
情况6:try{ return;}catch(){return;} finally{return;}
          程序执行try块中return之前(包括return语句中的表达式运算)代码;
          有异常:执行catch块中return之前(包括return语句中的表达式运算)代码;
                       则再执行finally块,因为finally块中有return所以提前退出。
          无异常:则再执行finally块,因为finally块中有return所以提前退出。

最终结论:任何执行try 或者catch中的return语句之前,都会先执行finally语句,如果finally存在的话。
                  如果finally中有return语句,那么程序就return了,所以finally中的return是一定会被return的,
                  编译器把finally中的return实现为一个warning。

 

下面是个测试程序public class FinallyTest  {public static void main(String[] args) { System.out.println(new FinallyTest().test());;}static int test(){int x = 1;try{x++;return x;}finally{++x;}}}结果是2。
分析:
在try语句中,在执行return语句时,要返回的结果已经准备好了,就在此时,程序转到finally执行了。在转去之前,try中先把要返回的结果存放到不同于x的局部变量中去,执行完finally之后,在从中取出返回结果,因此,即使finally中对变量x进行了改变,但是不会影响返回结果。它应该使用栈保存返回值。

61
 
1
 
 

  相关文章推荐
  •  有return的情况下try catch finally的执行顺序(最有说服力的总结)
  •  【直播】大中型UGC信息网站SEO分享--乔向阳
  •  try_catch_finally异常处理java
  •  【直播】打通Linux脉络 进程、线程和调度--宋宝华
  •  使用try-catch-finally处理异常
  •  【直播】Java最佳学习路线指导--肖海鹏
  •  Stress Testing压力测试(Stress Testing)是指模拟巨大的工作负荷以查看应用程序在峰值使用情况下如何执行操作
  •  【套餐】C++音视频实战技术套餐--夏曹俊
  •  try 与 catch finally关键字
  •  【套餐】0基础拿下HTML5和CSS3--李仁密
  •  java try…catch…finally捕获异常的实例
  •  【套餐】机器学习之数学基础系列--AI100
  •  Java中finally块执行与return关系深度剖析
  •  java try…catch嵌套捕获异常的实例
  •  Try Catch对效能的影响测试
  •  java 中finally语句块与return的执行关系
查看评论
19楼 落叶伤剑2017-04-13 19:06发表 [回复]
如果finally中没有return语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别,分以下两种情况,:

1)如果return的数据是基本数据类型或文本字符串,则在finally中对该基本数据的改变不起作用,try中的return语句依然会返回进入finally块之前保留的值。

2)如果return的数据是引用数据类型,而在finally中对该引用数据类型的属性值的改变起作用,try中的return语句返回的就是在finally中改变后的该属性的值。
Re: sinat_382681592017-06-08 20:22发表 [回复]
回复落叶伤剑:谢谢层主!
18楼 飘零雁2016-12-14 10:53发表 [回复]
catch 中有throw 的话,finally不会执行
Re: 口袋本人前天 14:31发表 [回复]
回复飘零雁:会执行的,建议你去实践一下。
17楼 baidu_351455222016-10-17 10:28发表 [回复]
针对第一点,如果catch块中有System.exit(0);那么finally块是不会执行的。try块中同样。
16楼 蜿蜒2016-08-21 10:42发表 [回复]
博主语意矛盾,给人以误解吧,先....之前,再.....,到底谁先谁后?
15楼 huangpingfeng2016-04-22 11:52发表 [回复]
try{ throw e; return;}catch(){throw e} finally{return;}
这种情况,执行了finally的return后,异常也是抛不出来
14楼 huangpingfeng2016-04-22 11:51发表 [回复]
try{ throw e; return;}catch(){throw e} finally{return;}
这种情况,执行了finally的return后,异常也是抛不出来
13楼 丶封刀看海2016-04-10 22:24发表 [回复]
学习了
12楼 thewindkee2016-03-07 21:57发表 [回复]
因为使用栈保存返回值,即使finally中执行i++,但是影响不到之前保存下来的具体的值。 所以return影响不了基本型的值。
而修改list ,map,自定义类等引用类型时,虽然进入finally之前保存了引用的地址,所以在finally中引用地址指向的内容改变了, 影响了返回值。
11楼 wangqiang54172016-03-06 01:33发表 [回复]
从SEH角度分析更容易理解
10楼 飞碟说2016-01-26 09:52发表 [回复]
逻辑清晰,浅显易懂,亲测之后果然如此,谢谢楼主。
9楼 -琥珀川-2015-08-26 14:36发表 [回复]
:try{ return;}catch(){return;} finally{return;}
程序执行try块中return之前(包括return语句中的表达式运算)代码;
有异常:执行catch块中return之前(包括return语句中的表达式运算)代码;
则再执行finally块,因为finally块中有return所以提前退出。
无异常:则再执行finally块,因为finally块中有return所以提前退出。

finally中有return会吃掉异常的
Re: wxb7745678762016-03-09 08:37发表 [回复]
回复最后一句话确实经典,一语惊醒。:
Re: 青蛙的世界2016-02-14 20:10发表 [回复]
回复-琥珀川-:大兄弟啊有个问题一直没搞懂你这最后一句话救了我的命啊
8楼 风雨常乐2015-05-08 09:39发表 [回复]
谢谢楼主
7楼 zspmaomao2014-11-25 10:05发表 [回复]
1.影响返回结果的前提是在 非 finally 语句块中有 return 且非基本类型
2.不影响返回结果 的前提是 非 finally 块中有return 且为基本类型

这也解释了,为什么Date类型是被修改的,究其本质 基本类型在栈中存储,返回的是真实的值,而引用类型返回的是其浅拷贝堆地址.所以才会改变~
6楼 浪羽清风2014-11-06 18:01发表 [回复]
引用“wangq2110”的评论:测试demo
[code=csharp]
static void Main(string[] ar...

基本数据类型是不能修改的,其他的可以修改,包括date
Re: wangq21102014-11-14 13:32发表 [回复]
回复浪羽清风:听不懂你在说啥!惜字如金啊!我只希望有人给出原因,而不是结论。
5楼 wangq21102014-10-24 16:02发表 [回复]
测试demo
[csharp] view plain copy
  1. static void Main(string[] args)  
  2.        {  
  3.          /*测试test1*/   
  4.            List<string>relist=test1();  
  5.            foreach (var item in relist)  
  6.            {  
  7.                Console.WriteLine(item);  
  8.            }  
  9.            Console.ReadLine();  
  10.        }  
  11.        private static List<string> test1()  
  12.        {  
  13.            List<string> strlist = new List<string>();  
  14.            strlist.Add("zs");  
  15.            strlist.Add("ls");  
  16.            strlist.Add("ww");  
  17.            strlist.Add("mz");  
  18.            try  
  19.            {  
  20.                strlist.Add("wq");  
  21.                return strlist;  
  22.            }  
  23.            finally  
  24.            {  
  25.                strlist.Add("yyy");  
  26.            }  
  27.        }  

测试输出结果:
zs
ls
ww
mz
wq
yyy
4楼 wangq21102014-10-24 15:57发表 [回复]
楼主,求真相。求解释。共同学习。
3楼 wangq21102014-10-24 15:55发表 [回复]
引用“pairsfish”的评论:楼主之写的有些片面,得出的结论是不正确的。finally修改的基本类型是不影响返回结果的。
修改li...

我也测试了,是你说的这样,是不是和return,finally的执行顺序无关,是不是值类型和引用类型搞的鬼。郁闷!
2楼 pairsfish2014-09-19 17:16发表 [回复]
楼主之写的有些片面,得出的结论是不正确的。finally修改的基本类型是不影响返回结果的。
修改list ,map,自定义类等引用类型时,是影响返回结果 的。
但是date类型经过测试是不影响的。有点奇怪。
Re: Marksinoberg2017-03-08 21:07发表 [回复]
回复pairsfish:date类型底层貌似是对long类型的数据的封装,也就是说JVM可能在编译的时候指定了一个常量值保存了起来,所以在finally块中修改的其实不是date底层所指向的那个副本,而是对类似于基本数据类型的修改,所以返回的结果仍然是一开始编译好的时候指定的副本。也就是没变的原因。

而其他的对象(引用类型)则是被finally块中的代码改变了所引用变量的真实数据,所以发生了改变。

也就是说,严格来讲,Date类型是个伪对象类型。

以上均为个人观点,如果有误,还望指出,大家一起研究。 :)
Re: lingzhm2015-08-19 16:29发表 [回复]
回复pairsfish:我试过了,果然如你所说。。。。真奇怪了。。。
Re: VirgoSoy2015-09-12 14:52发表 [回复]
回复lingzhm::本人新手,以下是自己的观点。。感觉与参数传值或传址类似。前几天才知道java全部都是传值的,即使是对象也是传递其地址的副本。return的若是对象,则先把对象的副本保存起来,也就是说保存的是指向对象的地址。若对原来的对象进行修改。对象的地址仍然不变,return的副本仍然是指向这个对象,所用finally中对对象的修改仍然有作用。而基本数据类型保存的是原原本本的数据,return保存副本后,在finally中修改都是修改原来的数据。副本中的数据还是不变,所以finally中修改对return无影响。。
Re: Marksinoberg2017-03-08 20:57发表 [回复]
回复VirgoSoy:我觉得你总结的很好,很有道理。Java关于方法返回值应该就是对这个引用(或者基本数据)而操作的。
1楼 Optimistic_2014-09-16 08:35发表 [回复]
学习了……
发表评论
  • 用 户 名:
  • zhoulovelian
  • 评论内容:
  • 插入代码
      
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
     
    kavensu
     
    • 访问:620521次
    • 积分:4873
    • 等级:  
    • 排名:第5919名
    • 原创:39篇
    • 转载:108篇
    • 译文:4篇
    • 评论:103条
    友情链接
    Parse 
    Strikingly(傻瓜式网页设计)
    文章分类
  • Android(45)
  • Android 数据存储(2)
  • Android 自定义UI控件(6)
  • Android 进程与线程(2)
  • Android 多媒体(3)
  • Android 编程规范(2)
  • PHP(1)
  • Java(19)
  • Web 开发(4)
  • 随笔(3)
  • 创业(1)
  • 软件安装及配置(9)
  • 有启发的时文(5)
  • 算法(9)
  • 计算机网络(9)
  • Epub(3)
  • 其他(6)
  • 操作系统(3)
  • 编译原理(1)
  • UML(1)
  • 笔试面试题(6)
  • C#开发(3)
  • JavaScrip & Node.js(5)
  • Git(1)
    文章存档
  • 2016年05月(1)
  • 2016年04月(1)
  • 2015年01月(1)
  • 2014年01月(10)
  • 2013年11月(1)
    展开
    阅读排行
  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)(133862)
  • 邮件协议POP3/IMAP/SMTP服务的区别(57078)
  • 【使用线程池的好处】多线程的环境中,尽量采用线程池(25782)
  • TableLayout和TableRow的使用(18333)
  • C#中SQL语句的参数写法(17579)
  • 使用HttpClient通过POST方式发送XML,使用TCP/IP Monitor观察数据(16685)
  • javascript 对象数组排序(15445)
  • node.js常用模块(15132)
  • onContextItemSelected 与 onMenuItemSelected 的那些事(14486)
  • OSI的七层模型,网线,网卡,集线器,交换机,路由器分别工作在七层模型中的哪一层?(13713)
    评论排行
  • 2013网易技术类笔试题(java开发方向+移动平台开发)(30)
  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)(28)
  • onContextItemSelected 与 onMenuItemSelected 的那些事(6)
  • 使用ActivityGroup时,在Activity中显示对话框出现的问题(5)
  • 条码扫描二维码扫描——ZXing android(4)
  • 网页分页数据抓取的几种方式(3)
  • 网上下载图片并保持到SD卡中+读取SD卡中的图片(2)
  • 【使用线程池的好处】多线程的环境中,尽量采用线程池(2)
  • Android中Fragment的应用(android官方教程完美翻译)(2)
  • 用点画分隔线(2)
    推荐文章
    • * CSDN日报20170828——《4个方法快速打造你的阅读清单》
    • * CSDN博客模板调查问卷
    • * 秒杀系统的一点思考
    • * TCP网络通讯如何解决分包粘包问题
    • * 技术与技术人员的价值
    • * GitChat·人工智能 | 除了深度学习,机器翻译还需要啥?
    最新评论
  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    口袋本人: @mochounv:会执行的,建议你去实践一下。

  • 【使用线程池的好处】多线程的环境中,尽量采用线程池

    weixin_38310495: 666

  • 【使用线程池的好处】多线程的环境中,尽量采用线程池

    health7788: 厉害了

  • 2013网易技术类笔试题(java开发方向+移动平台开发)

    针叶: 感觉大公司的笔试面试就是另一种方式的计算机考研。

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    sinat_38268159: @aliangshuang:谢谢层主!

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    落叶伤剑: 如果finally中没有return语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别...

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    Marksinoberg: @pairsfish:date类型底层貌似是对long类型的数据的封装,也就是说JVM可能在编译的时...

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    Marksinoberg: @VirgoSoy:我觉得你总结的很好,很有道理。Java关于方法返回值应该就是对这个引用(或者基本...

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    飘零雁: catch 中有throw 的话,finally不会执行

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    baidu_35145522: 针对第一点,如果catch块中有System.exit(0);那么finally块是不会执行的。tr...

阅读全文
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 干咳咳不出来怎么办 咳嗽咳不出来怎么办 手机开机没反应怎么办 企业年金离职后怎么办 辞职后企业年金怎么办 未来农村老房子怎么办 房价太高老百姓怎么办 联通混改临时工怎么办 插头是圆柱形的怎么办 被直销骗了怎么办 u盘格式化写保护怎么办 u盘无法格式化怎么办? qq忘了密码怎么办 行李箱密码坏了怎么办 wifi忘了密码怎么办 皮箱密码锁忘了怎么办 皮箱密码忘了怎么办 行李箱密码忘了怎么办? 手提箱密码忘了怎么办 箱子密码忘记了怎么办 支付功能被关闭怎么办 竞争性谈判流标怎么办 发票忘记作废,税怎么办 土地使用证丢了怎么办 电话被标记诈骗怎么办 天刀玩起来很卡怎么办 花肥是什么吃了怎么办 花肥是去根部怎么办 红掌叶子下垂怎么办 ofo换手机号了怎么办 城管不让挂招牌怎么办 房贷审批不通过怎么办 工伤认定下来后怎么办 在外地办理公司怎么办 游戏停服充的钱怎么办 头发定型后悔了怎么办 有很多白头发怎么办 头顶碎发太多怎么办 前额碎头发多怎么办 三类维修许可证怎么办 通行证快过期了怎么办