黑马程序员技术交流社区

标题: finally的一个小问题! [打印本页]

作者: 余银桂    时间: 2012-6-22 23:32
标题: finally的一个小问题!
本帖最后由 余银桂 于 2012-6-22 23:53 编辑
  1. public class  Test6

  2. {

  3.       public static void  main(String args[])

  4.       {

  5.             Test6 t  = new  Test6();

  6.             int  b  =  t.get();

  7.             System.out.println(b);

  8.       }

  9.       

  10.       public int  get()

  11.       {

  12.             try

  13.             {

  14.                   return 1 ;

  15.             }

  16.             finally

  17.             {

  18.                   return 2 ;

  19.             }

  20.       }

  21. }
复制代码
运行结果返回是 2   
我想知道 程序的执行过程,为什么会返回 2
finally 的主要作用又是什么?
作者: 丁二跃    时间: 2012-6-22 23:41
finally 代码块里的内容是在最后程序执行前执行的。一般和 try catch 一起用,无论是否出现异常都要执行,来做资源清理工作。
  1. public class T {
  2. public static void main(String[] args) {
  3.          new T().dis();
  4. }

  5. int dis(){
  6.          System.out.println("hello");
  7.          try{
  8.                  return dd();
  9.          }finally{
  10.                  System.out.println("nihao ");
  11.                  return 1;
  12.          }
  13. }

  14. int dd(){
  15.          System.out.println("ni lai le ");
  16.          return 3;
  17. }
  18. }


  19. 结果:hello
  20. ni lai le
  21. nihao
复制代码
可以看出finally 内的代码是在 try中return执行过程中,但还没执行完时执行的……
作者: 薄炳鑫    时间: 2012-6-22 23:47
finally的作用一般是用来释放资源的,比如数据库连接完成后,一般都要关闭数据库连接。这个关闭数据库资源的代码就放在finally代码块中。
finally中的代码是肯定要执行的,你这个代码的执行过程就是先给返回一个1给b,然后执行finally中的代码,将1替换成2。所以最后打印的就是2.
作者: 孙浩迪    时间: 2012-6-22 23:48
finally 一般作用是关闭资源用的, 比如关闭流之类的。 无论代码是怎么样的,最后都必须执行finally{}     代码里面的东西的。
作者: 余银桂    时间: 2012-6-22 23:50
薄炳鑫 发表于 2012-6-22 23:47
finally的作用一般是用来释放资源的,比如数据库连接完成后,一般都要关闭数据库连接。这个关闭数据库资源的 ...

刚刚写了几个输出打印,大概了解了,只是没接触过 finally ... 不知道是啥玩意
作者: 丁二跃    时间: 2012-6-22 23:52
薄炳鑫 发表于 2012-6-22 23:47
finally的作用一般是用来释放资源的,比如数据库连接完成后,一般都要关闭数据库连接。这个关闭数据库资源的 ...

不对吧,程序不可能把1给b后 再跳回来执行finally吧?执行过return就从方法里跳出了啊……应该是再执行return 1 过程中 执行finally里的代码,跳出该方法……
作者: 吴小铁你好    时间: 2012-6-22 23:55
你这是一个try{}finally{}语句,finally语句里语句必须执行。
在你这个程序中先t.get()调用get()方法,程序按顺序执行,先执行try语句,执行后再执行finally语句,有用你定义的是int b为栈内存,就return 2.所以b=2.
作者: 孙峰    时间: 2012-6-22 23:55
        finally 代码块中的代码在一般情况下是一定会执行的。   这里主要是对一些系统资源占用的终止。 因为该代码块和try 一起使用时,如果发生异常,则部分系统资源的占用就无法释放, 此时 就是finally 代码块发挥作用的时候了。      当然也不是肯定都会执行,比如 此前有语句:System.exit(0);  系统退出语句,JVW结束,也就执行不到了。
作者: 余银桂    时间: 2012-6-22 23:56
丁二跃 发表于 2012-6-22 23:52
不对吧,程序不可能把1给b后 再跳回来执行finally吧?执行过return就从方法里跳出了啊……应该是再执行re ...

也就是返回值的时候 只返回了 2 ? 那个 try中的 1 没有返回给b ?

我开始也是以为是 返回了 1 之后 再返回 2 替换了值
作者: 薄炳鑫    时间: 2012-6-22 23:58
丁二跃 发表于 2012-6-22 23:52
不对吧,程序不可能把1给b后 再跳回来执行finally吧?执行过return就从方法里跳出了啊……应该是再执行re ...

我觉得他最后肯定要执行那个finally中的那个return 2;的代码,所以应该就是把2 付给b了。
作者: 燃烧端午    时间: 2012-6-23 00:00
finally 语句块是在 try 或者 catch 中的 return 语句之前执行的。
作者: 丁二跃    时间: 2012-6-23 00:00
余银桂 发表于 2012-6-22 23:56
也就是返回值的时候 只返回了 2 ? 那个 try中的 1 没有返回给b ?

我开始也是以为是 返回了 1 之后 再 ...

你看我 上面那个程序,很明显在 try中的 return 过程中调用了fianlly,既然调用了finally,那其里面的return 执行后不是要跳出这个方法了吗?^^^那么try 中return的 执行就没有进行到底,也就没返回

一个方法怎么会在一次调用中返回两个值呢?!
作者: 余银桂    时间: 2012-6-23 00:00
孙峰 发表于 2012-6-22 23:55
finally 代码块中的代码在一般情况下是一定会执行的。   这里主要是对一些系统资源占用的终止。 因 ...

那 try 中的  return 1 有没有执行?
作者: 丁二跃    时间: 2012-6-23 00:05
薄炳鑫 发表于 2012-6-22 23:58
我觉得他最后肯定要执行那个finally中的那个return 2;的代码,所以应该就是把2 付给b了。 ...

那是肯定的,只不过 那个一 应该没有被返回……一次调用哪能返回两个值呢
作者: 丁二跃    时间: 2012-6-23 00:06
余银桂 发表于 2012-6-23 00:00
那 try 中的  return 1 有没有执行?

执行了,没执行完   把1 换成个方法,在方法里加上打印语句  象我 上面的代码  就可以看出来了
作者: 余银桂    时间: 2012-6-23 00:11
丁二跃 发表于 2012-6-23 00:06
执行了,没执行完   把1 换成个方法,在方法里加上打印语句  象我 上面的代码  就可以看出来了 ...

先谢谢你了,我再研究研究一下,有点混乱了
作者: 孙峰    时间: 2012-6-23 00:33
余银桂 发表于 2012-6-23 00:00
那 try 中的  return 1 有没有执行?

return 1 也执行了, 执行之后又执行finally ,又返回了2,重新赋值了,  你可以看下老毕的 第10 天视频第一个,在6‘20”的位置
作者: 黄奕豪    时间: 2012-6-23 11:23
public class  Test5

{

      public static void  main(String args[])

      {

            Test5 t  = new  Test5();

            int[]  b  =  t.get();
            for(int i : b)
            {
                    System.out.println(i);
            }

      }

      

      public int[]  get()

      {
             //原值4和5,打印的是1和2,说明这两个代码都执行了,你的那个输出2是被覆盖的!
            int[] arr = {4,5};
            try

            {
                    arr[0]=1;
                  return arr ;

            }

            finally

            {
                      arr[1]=2;
                  return arr ;

            }

      }

}
作者: 丁二跃    时间: 2012-6-23 11:36
黄奕豪 发表于 2012-6-23 11:23
public class  Test5

{

黄老大 这个也不能说明 返回 1 然后2 又覆盖了啊

执行完 arr[0]=1 后数组变成 {1,5}

在执行 finally 中代码 返回 {1,2}

不能说明问题啊

还是认为一个方法在一次调用中 不可能返回2 个值
作者: 黄奕豪    时间: 2012-6-23 11:46
丁二跃 发表于 2012-6-23 11:36
黄老大 这个也不能说明 返回 1 然后2 又覆盖了啊

执行完 arr[0]=1 后数组变成 {1,5}

怎么说呢?return语句后面一般都不会执行的,但是这是个特殊情况,只能说实际开发中一般不会出现这种情况,想了一下,你可以把他理解为开始打算返回了1,后面一看还有finally语句,这个finally是老大,肯定得看看他有什么指示,是吧?结果他说返回2,不要1了。所以就把方法体里面打算返回的1给覆盖了!函数不会有两个返回值,1是在get()函数里面被覆盖的!这个并不违背它。因为执行finally的时候这个函数还没有结束,而返回值是要在函数结束后才返回的!
作者: 余银桂    时间: 2012-6-23 11:47
丁二跃 发表于 2012-6-23 11:36
黄老大 这个也不能说明 返回 1 然后2 又覆盖了啊

执行完 arr[0]=1 后数组变成 {1,5}

昨晚翻阅了一下,看到有一个地方是这么讲解的。

try 中的return语句执行后,将把返回结果放置进函数栈中,此时函数并不是马上返回,它要执行finally语句后才真正开始返回。

作者: 孙峰    时间: 2012-6-23 11:54
黄奕豪 发表于 2012-6-23 11:23
public class  Test5

{

斑竹不给分 抗议 抗议:@
作者: 李海晓    时间: 2012-6-23 11:56
只能return返回一次,应为执行return 时,函数就结束了。try中的return没有返回结果,finally中的才返回结果
作者: 黄奕豪    时间: 2012-6-23 11:57
孙峰 发表于 2012-6-23 11:54
斑竹不给分 抗议 抗议

哥,我错了!!可是你看看,哪个是重点啊?
finally 代码块中的代码在一般情况下是一定会执行的。   这里主要是对一些系统资源占用的终止。 因为该代码块和try 一起使用时,如果发生异常,则部分系统资源的占用就无法释放, 此时 就是finally 代码块发挥作用的时候了。      当然也不是肯定都会执行,比如 此前有语句:System.exit(0);  系统退出语句,JVW结束,也就执行不到了。

作者: 蔡建荣    时间: 2012-6-23 12:11
return 1 应该没有执行  执行了就是返回值了结束了 应该是直接跳接到finally执行其中语句。 直接赋予get()方法return2

finally方法毕老师的视频里有讲噢~  finally 利用它一定会执行到它代码块的特点,在try catch中有异常时用finally对停止系统资源占用。不然有异常了部分系统资源会被占有,卡在那里。
作者: 孙峰    时间: 2012-6-23 13:58
黄奕豪 发表于 2012-6-23 11:57
哥,我错了!!可是你看看,哪个是重点啊?
finally 代码块中的代码在一般情况下是一定会执行的。   这里 ...

那哥们不是问finally的主要作用了嘛
作者: 游洪波    时间: 2012-6-23 15:02
嘿嘿,我在做笔试题的时候有一个这样的问题:try{}catch{}中的finally{}中的代码会不会被执行,如果会是在return前还是return 后
答案是  会被执行,return前执行,那么这样的话你是不是会明白一点呢?
public int  get()



      {



            try



            {



                  return 1 ;



            }



            finally



            {



                  return 2 ;



            }



      }
你这个方法在执行的时候首先执行到try里边的时候执行到在执行到return语句的时候他会提前执行 finally中的语句 刚好你里边写了一个return 2; return的意思是跳出这个方法 所以你收到的返回值是2;也就是说你try中的return 根本没有被执行,你如果改成
        try{
                        return 1;       
                }finally{
                        System.out.println("finally");
                }
你试试,他会先输出finally然后给你返回一个1,我改完以后跟你的区别就在于,你在finally中直接使用return退出了方法而我没有 所以我try中的return 1还是会被执行的。
作者: 游洪波    时间: 2012-6-23 15:06
  public int[]  get()

      {
             //原值4和5,打印的是1和2,说明这两个代码都执行了,你的那个输出2是被覆盖的!
            int[] arr = {4,5};
            try

            {
                    arr[0]=1;
                  return arr ;

            }

            finally

            {
                      arr[1]=2;
                  return arr ;

            }

      }
我想给你说下 ,你可以把try中的 return 去掉试试,结果还是会一样的  应为finally里边的代码只会在return前执行,所以说你try中的return arr;形同虚设
作者: 孙峰    时间: 2012-6-23 18:42
黄奕豪 发表于 2012-6-23 11:57
哥,我错了!!可是你看看,哪个是重点啊?
finally 代码块中的代码在一般情况下是一定会执行的。   这里 ...

:kiss:{:3_51:}
作者: oracleserver    时间: 2012-6-24 21:36
有些异常如果不处理,也就不会继续下去了。即程序从catch里改变控制流,不会执行后面的语句。加了finally,可以保证即使因为异常,后面的代码不会被执行,但是finally里面的语句还是会执行,这样可以释放一些申请的资源~或者做一些其他工具,比如作profiling统计等。所以在try{}中的finally是一定会执行的。为了程序的健壮性,不能在用户使用的时候在一些突发小异常的照成程序直接终止。






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