黑马程序员技术交流社区

标题: 新人,基础测试题中关于finally与return的执行顺序问题, [打印本页]

作者: 王清华0    时间: 2013-8-8 15:55
标题: 新人,基础测试题中关于finally与return的执行顺序问题,
本帖最后由 王清华0 于 2013-8-8 22:27 编辑

黑马测试题中的第八题:写一个类证明return是在finally执行后才返回的,且在finally无法改变返回值。在《java核心技术》中给的解释是:
return在try中,则保留返回值,执行完finally之后才返回,并且finally中无法改变返回值。
return在finally中,则在执行finally的过程中,优先执行这个返回,覆盖掉try中的返回值。
return在try{}finally{}之外的话 ,finally改变的值会作为return的返回值。
那么按照这个说法,我们的测试题明显是针对第一种情况问的了,我答题的代码如下:
  1. public class Test8 {
  2.         public static void main(String args[]){
  3.                 int var = 4;
  4.                 System.out.println("第一次调用,证明finally无法改变return的值,var此时的值为:"+method_1(var));
  5.                 System.out.println("第二次调用,证明try中的return晚于finally,var此时的值为:"+method_2(var));

  6.         }
  7.         //第一个函数,在try中返回var的值,在finally中改变var的值,输出结果为改变finally改变之前的,证明finally无法
  8.         //改变返回值
  9.         public static int method_1(int var){
  10.                 try{
  11.                         var = 5;
  12.                         return var;
  13.                 }
  14.                 finally{
  15.                         var=6;
  16.                         }
  17.         }

  18.         //第二个函数,在try和 finally中都返回var的值,根据java的原则,遇到第一个return即返回,不再执行接下来的return语句。
  19.         //如果返回值为5,则优先执行try中的return,如果返回值为6,则优先执行了finally中的return。
  20.         @SuppressWarnings("finally")
  21.         public static int method_2(int var){
  22.                 try{
  23.                         var = 5;
  24.                         return var;
  25.                 }finally{
  26.                         var = 6;
  27.                         return var;
  28.                 }
  29.         }
  30. }
复制代码
结果也是按照我注释的结果体现的,证明了题目要求。
但是我总是觉得这种证明方式有取巧的嫌疑,我觉得能不能用线程sleep的形式直观的表现出来其执行顺序,但是我写了多次都没有写出正确的程序,求助。

作者: oath    时间: 2013-8-8 17:13
  1. class Test07
  2. {       
  3.         public static String boov(String str)
  4.         {       
  5.                 try
  6.                 {                       
  7.                         str="“return返回给boov”";
  8.                         return str;               
  9.                 }
  10.                 finally
  11.                 {       
  12.                         System.out.println("finally执行");
  13.                         //如果return是在finally执行后才返回,则这句话先打印一次,然后返回try中的str值。
  14.                         str="finally里的语句";//在finally中为str赋值
  15.                 }                               
  16.         }       
  17.         public static void main(String[] args)
  18.         {       
  19.                 String Str = null;
  20.                 String newStr=boov(Str);
  21.                 System.out.println(newStr);
  22.         }       
  23. }
  24. /**该程序运行后,
  25. *
  26. * 1、
  27. *         “finally执行” 先于  “return返回给boov” 被打印,说明return是在finally执行后才返回的
  28. * 2、
  29. *         在finally中改变了str的值,但返回的结果仍然是return中的str值,说明在finally没有改变返回值。
  30. */
复制代码

作者: 王清华0    时间: 2013-8-8 17:40
oath 发表于 2013-8-8 17:13

不对吧,这也是我最初想到的方法,但是这样子只能证明finally无法改变返回值而已,不能证明其先后顺序。
因为打印“finally执行”的这一句是在被调用函数boov()里面执行的,而打印“return返回给boov”则是已经在main()函数中了。原本就应该是这个执行顺序啊。感觉还不如我的证明方式有说服力呢。
因为我们 都想到用return的返回值输出结果晚于finally之后,来证明其执行顺序问题,但是问题就在于,return只能是返回值,而输出这个返回值已经是原函数的执行问题了,等于是偷换了问题的题目。因此核心问题就是return只是单纯的返回值,而我们无法在控制台中明确的知道这个返回的执行时间。
因此我才觉得用线程sleep的方式更加好,让finally的执行 延迟3到5秒,这绝对已经超出了return的执行时间,或者是,有一个类似于监听器 的东西,可以监听return这个事件。这样子才更加直白有说服力一些。但是仍然谢谢了。
作者: oath    时间: 2013-8-8 18:31
王清华0 发表于 2013-8-8 17:40
不对吧,这也是我最初想到的方法,但是这样子只能证明finally无法改变返回值而已,不能证明其先后顺序。
...

疏忽了 ,,呵呵   你看下面的,,可不可以证明finally是先执行的
  1. public static void main(String[] args)
  2.         {       
  3.                        
  4.                 try
  5.                 {                                       
  6.                         return;//程序执行到这里会结束,如果return先于finally执行,,,到这里就结束了,
  7.                 }                               
  8.                 finally
  9.                 {       
  10.                         System.out.println("finally执行");                                       
  11.                 }                               
  12.        
  13.         }       
复制代码

作者: oath    时间: 2013-8-8 19:22
本帖最后由 oath 于 2013-8-8 19:51 编辑
王清华0 发表于 2013-8-8 17:40
不对吧,这也是我最初想到的方法,但是这样子只能证明finally无法改变返回值而已,不能证明其先后顺序。
...

好像是finally把值改了,return它一执行又把值给改回去了,

所以在finally无法改变返回值




这不就是说finally是先执行的吗,这一题里面的问题其实就是一个问题

作者: 王清华0    时间: 2013-8-8 19:46
oath 发表于 2013-8-8 18:31
疏忽了 ,,呵呵   你看下面的,,可不可以证明finally是先执行的

这个方式貌似可以,单纯的以main函数的结束来证明finally优于return,但是还是感觉有取巧的嫌疑,我是求线程sleep方式或者监听器的方式,这样 证明更加直观。
作者: 王清华0    时间: 2013-8-8 19:47
oath 发表于 2013-8-8 19:22
其实  在finally中无法改变返回值 ,就已经说明了finally是先执行的,,,

啊?这个逻辑有点不对啊,为啥他没有改变就证明 先执行呢?这个完全相反吧 。
作者: oath    时间: 2013-8-8 19:54
王清华0 发表于 2013-8-8 19:47
啊?这个逻辑有点不对啊,为啥他没有改变就证明 先执行呢?这个完全相反吧 。 ...

finally先执行,值被改了,return它一执行又把值给改回去了,

so 在finally无法改变返回值


作者: oath    时间: 2013-8-8 20:02
本帖最后由 oath 于 2013-8-8 20:04 编辑
王清华0 发表于 2013-8-8 19:46
这个方式貌似可以,单纯的以main函数的结束来证明finally优于return,但是还是感觉有取巧的嫌疑,我是求 ...

呵呵 是啊,,你的证法,先不管对错,,涉及到的知识肯定是更多的

但  你看啊,他出这个题 要证明两个问题 但其实有一个是迷雾弹
要是看清楚了,这其实就是一个问题
但要是拼命去证两个,是不是   已经中套了

这个是个人看法   你的思路很好  要是有谁会,,,赶紧贴出来看下哈  呵呵  

作者: 王清华0    时间: 2013-8-8 20:35
oath 发表于 2013-8-8 20:02
呵呵 是啊,,你的证法,先不管对错,,涉及到的知识肯定是更多的

但  你看啊,他出这个题 要证明两个问 ...

我和你看法不一样
首先是try中的return的值以及finally的改变,我认为是return保存返回值 ,finally执行完了之后才执行返回,而不是finally中改一遍 return再改一遍。
再一个是关于这个题目,我觉得这两问不能归为一个,我还是觉得按照你的方式逻辑无法证明。
作者: 白堇翎    时间: 2013-8-8 21:05
  1. package day01;

  2. public class test7
  3. {        
  4.         public static String boov(String str)
  5.         {        
  6.                 try
  7.                 {                        
  8.                         str="“return返回给boov”";
  9.                         return demo.demo_1();               
  10.                 }
  11.                 finally
  12.                 {        
  13.                         System.out.println("finally执行");
  14.                         return demo.demo_2();
  15.                 }                                
  16.         }        
  17.         public static void main(String[] args)
  18.         {        
  19.                 String Str = null;
  20.                 String newStr=boov(Str);
  21.                 System.out.println(newStr);
  22.         }        
  23. }

  24. class demo{
  25.         public static String demo_1(){
  26.                 System.out.println("Demo1");
  27.                 return "demo1";
  28.         }
  29.         public static String demo_2(){
  30.                 System.out.println("Demo2");
  31.                 return"demo2";
  32.         }
  33. }
复制代码
你试一下这一段代码就知道了
try中的return的确被执行了,你可以想象成这个return被放进了一个临时容器,但是下面还有一个finally需要执行,这个时候boov没有立刻结束,而是等finally中的代码执行完了以后才返回,可是很不巧 finally中又有一个return,这个return也进去了临时容器,把前面的return给覆盖掉了...
其实这道题的考察重点并不在这里..因为没有人蛋疼的在finally里写return,假如你在finally里写了return 那你这段程序前面的那一大段代码就变得毫无意义了..反正它怎么执行,怎么return,最终返回的还是我finally里的return...

不知道这样回答你能不能明白

作者: oath    时间: 2013-8-8 21:06
王清华0 发表于 2013-8-8 20:35
我和你看法不一样
首先是try中的return的值以及finally的改变,我认为是return保存返回值 ,finally执行 ...

我的意思是 return 保存返回值   ,就像return的值被final修饰了一样,finally中的语句可以执行的话,值肯定是被改过,不信你在finally中加进return,返回的就是finally中的值了  
作者: oath    时间: 2013-8-8 21:11
如果有return的源文件  扒出来看下就好了
作者: 王清华0    时间: 2013-8-8 21:13
白堇翎 发表于 2013-8-8 21:05
你试一下这一段代码就知道了
try中的return的确被执行了,你可以想象成这个return被放进了一个临时容器,但是 ...

哥们,是你不明白吧,请仔细看我原来的代码,你的这个跟我原来的代码根本就是没有区别啊。。。。。。
都是利用finally中的return覆盖掉try中的return借以证明finally先执行,但是这个依赖于java的原有特性,每个函数最多只有一个return,执行完第一个return之后其他的不再执行。
我要的是,不利用这个特性 ,而借助于线程 sleep()或者监听器来实现的方法。
作者: 王清华0    时间: 2013-8-8 21:15
oath 发表于 2013-8-8 21:06
我的意思是 return 保存返回值   ,就像return的值被final修饰了一样,finally中的语句可以执行的话,值 ...

大哥,看看我最初贴上去的代码,就是在finally中加入return的啊,但是这个要借助于java最多只有一次return的特性。我要的是不借助这个特性的方法啊。
作者: oath    时间: 2013-8-8 21:18
王清华0 发表于 2013-8-8 21:15
大哥,看看我最初贴上去的代码,就是在finally中加入return的啊,但是这个要借助于java最多只有一次retur ...

:handshake
作者: 白堇翎    时间: 2013-8-8 21:43
王清华0 发表于 2013-8-8 21:13
哥们,是你不明白吧,请仔细看我原来的代码,你的这个跟我原来的代码根本就是没有区别啊。。。。。。
都 ...

你再仔细看看有没有区别  我新建一个类不是没有原因的 你仔细看看打印顺序就知道哪个return先执行了.
但是执行不代表返回
作者: 王清华0    时间: 2013-8-8 21:55
白堇翎 发表于 2013-8-8 21:43
你再仔细看看有没有区别  我新建一个类不是没有原因的 你仔细看看打印顺序就知道哪个return先执行了.
但 ...

看懂了,我的,我看错了。
作者: 清风有意    时间: 2014-3-2 22:46
白堇翎 发表于 2013-8-8 21:05
你试一下这一段代码就知道了
try中的return的确被执行了,你可以想象成这个return被放进了一个临时容器,但是 ...

启发了我finally中代码的作用。。说得好




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2