A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张吉日 中级黑马   /  2012-10-18 12:58  /  2146 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张吉日 于 2012-10-18 16:48 编辑

为什么finally里面的n--之后 try里面的return  n的值没有--    这里面是什么原理
  1. public class Demo {
  2.         /*
  3.          * mian函数,程序的入口
  4.          */
  5.         public static void main(String[] args){
  6.                 System.out.println(function());
  7.         }
  8.         /*
  9.          * 定义功能方法
  10.          */
  11.         public static int function(){
  12.                
  13.                 int n = 5;                                        // 定义局部变量
  14.                
  15.                 try{
  16.                
  17.                                                                         // 定义返回值
  18.                         return n;                                // 运行结果n的值没有改变,还是 5
  19.                 }
  20.                 finally{
  21.                         n--;                                        // 将n--之后的值打印出来。
  22.                         
  23.                         System.out.println(n);        // n的值 打印是4
  24.                 }
  25.         }
  26. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1

查看全部评分

7 个回复

正序浏览
王威 发表于 2012-10-18 13:22
我给你的代码设了个断点,debug跟踪了一下,发现执行完finally里面的语句后
然后再执行main()方法里打印语 ...

是Myeclipse里面的断点吗,我懂了
回复 使用道具 举报
给楼主一个最完整的答复吧,这个问题是这样的:当java程序执行try块、catch块时遇到了return或throw语句,这两个语句都会导致该方法立即结束,但是系统执行这两个语句并不会结束该方法,而是去寻找该异常处理中的finally块,如果没有finally块,程序立即执行return或throw语句,方法终止。如果有finally块,系统立即开始执行finally块,只有当finally块执行完成后,系统才会再次跳回来执行try块、catch块里的return或throw语句。如果finally块里也使用了return或它throw等导致方法终止的语句,finally块已经终止了方法,系统将不会跳回去执行try、catch块里的任何代码。

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1

查看全部评分

回复 使用道具 举报
这就是一个返回值压栈出栈的问题
1.首先是执行try中的语句当执行到return时 n的值还没有改变 但这时返回值被压栈了(也就是存储到了一个临时的空间中了)
2.然后再执行finally中的语句 finally中执行完后 并没有改变返回值因为他另存到一个空间了
3.返回值出栈
回复 使用道具 举报
本帖最后由 葬天 于 2012-10-18 13:40 编辑

参考《 The JavaTM Virtual Machine Specification, Second Edition 》中 7.13 节 Compiling finally

Java 虚拟机编译 finally 语句块时,实际上,Java 虚拟机会把 finally 语句块作为 subroutine,直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。但是,还有另外一个不可忽视的因素,那就是在执行 subroutine(也就是 finally 语句块)之前,try 或者 catch 语句块会保留其返回值到本地变量表(Local Variable Table)中。待 subroutine 执行完毕之后,再恢复保留的返回值到操作数栈中,然后通过 return 或者 throw 语句将其返回给该方法的调用者(invoker)。
回复 使用道具 举报
当运行到try块中return语句时,n的值会保留。然后跳到finally块中执行里面的语句,执行完毕后,回到return运行。finally中的n值不会影响try块中的。
回复 使用道具 举报
本帖最后由 王威 于 2012-10-18 13:33 编辑
  1. public class Demo {
  2.         /*
  3.          * mian函数,程序的入口
  4.          */
  5.         public static void main(String[] args){
  6.                 System.out.println(function());
  7.         }
  8.         /*
  9.          * 定义功能方法
  10.          */
  11.         public static int function(){
  12.                
  13.                 int n = 5;                                        // 定义局部变量
  14.                
  15.                 try{
  16.                      return n;                                // 运行结果n的值没有改变,还是 5
  17.                 }
  18.                 finally{
  19.                         n--;                                        // 将n--之后的值打印出来。
  20.                         System.out.println(n);        // n的值 打印是4
  21.                 }
  22.         }
  23. }
复制代码
我给你的代码设了个断点,debug跟踪了一下,发现执行完finally里面的语句后
然后再执行main()方法里打印语句的时候System.out.println(function()); ,我跟进去看了下,
这个输出语句传进去的参数是5,说明当执行try语句时n=5已经返回去了只是没有打印出来而已,先等
finally执行完以后再来打印。
也就是说,如果try语句体中含有return语句,就会把要return的值存放在一个不同于n的变量中,当finally执行完后
再从中取出值,所以你在finally中改变n的值不会影响try中要返回的值,因为这是从先前保存的另一个不同于n的变量中取得的

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1

查看全部评分

回复 使用道具 举报
需要理解这个程序try和finally的执行顺序。
当我们把try中数据运算出来,到return 的时候,它会先把得到的n放在主函数那儿,然后就不运行了,先运行finally的代码,当finally的代码运行完后,就再运行return的代码,但是n的值还是原来那个,并不是finally后面的。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马