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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 秦冲 黑马帝   /  2012-5-29 12:51  /  2419 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 秦冲 于 2012-5-29 12:49 编辑
  1. public class Test {
  2. public static void main(String[] args) {
  3.         System.out.println("return value of getValue(): " + getValue());
  4.          }

  5. public static int getValue() {
  6.         try {
  7.                  return 0;
  8.         } finally {
  9.                  return 1;
  10.                 }
  11.          }
  12. }
复制代码
执行结果:return value of getValue(): 1
  1. public class Test {
  2.       public static void main(String[] args) {
  3.              System.out.println("return value of getValue(): " + getValue());
  4.       }
  5.       public static int getValue() {
  6.                 int i = 1;
  7.             try {
  8.               return i;
  9.           } finally {
  10.                i++;
  11.            }
  12.        }
  13.         }
复制代码
执行结果:
return value of getValue(): 1
  1. public class Test {
  2.     public static void main(String[] args) {  
  3.         System.out.println(test());  
  4.   }  
  5.    public static String test() {  
  6.        try {  
  7.            System.out.println("try block");  
  8.            return test1();  
  9.      } finally {  
  10.             System.out.println("finally block");  
  11.      }  
  12.   }  
  13.    public static String test1() {  
  14.         System.out.println("return statement");  
  15.          return "after return";  
  16.    }  
  17. }
复制代码
执行结果
try block
return statement
finally block
after return

我知道finally 语句块是在 try 或者 catch 中的 return 语句之前执行的。 由此,可以轻松的理解第一个的执行结果是 1。因为 finally 中的 return 1;语句要在 try 中的 return 0;语句之前执行,那么 finally 中的 return 1;语句执行后,把程序的控制权转交给了它的调用者 main()函数,并且返回值为 1。那为什么第二个 的返回值不是 2,而是 1 呢?按照第一个的分析逻辑,finally 中的 i++;语句应该在 try 中的 return i;之前执行啊? i 的初始值为 1,那么执行 i++;之后为 2,再执行 return i;那不就应该是 2 吗?怎么变成 1 了呢?
前面有人发帖出现过这个问题,感觉似懂非懂。

Java 虚拟机是如何编译 finally 语句块的问题?
参考《 The JavaTM Virtual Machine Specification, Second Edition 》中 7.13 节 Compiling finally。那里详细介绍了 Java 虚拟机是如何编译 finally 语句块。
Java 虚拟机会把 finally 语句块作为 subroutine(对于这个 subroutine 不知该如何翻译为好,干脆就不翻译了,免得产生歧义和误解。)直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。但是,还有另外一个不可忽视的因素,那就是在执行 subroutine(也就是 finally 语句块)之前,try 或者 catch 语句块会保留其返回值到本地变量表(Local Variable Table)中。待 subroutine 执行完毕之后,再恢复保留的返回值到操作数栈中,然后通过 return 或者 throw 语句将其返回给该方法的调用者(invoker)。请注意, return、throw 和 break、continue 有区别,对于保留返回值,只适用于 return 和 throw 语句,不适用于 break 和 continue 语句,因为它们根本就没有返回值。
根据上面的说明:return test1();
这条语句等同于 :
String tmp = test1();
return tmp;

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

2 个回复

倒序浏览
呃,你应该看过前几天有个哥们问的那个问题了吧~~~
finally只有一种情况不执行,除此之外他都需要执行里面的语句,那就是虚拟机退出,相当于整个java运行环境结束了,即调用了System.exit(参数)
你只要知道这点你就能解释上面的问题了,不管是执行到了return还是出现了什么异常,都会去执行finally语句,有的时候不要把一个地方想的太死,我们都知道函数遇到return就结束但是在try catch finally 中并没有结束还需要执行finally中的语句呢。。。
回复 使用道具 举报
finally在程序结束前必须执行
第二个:i++是在主函数输出语句之后执行的,所以最后输出的是1,如果在finally{i++;System.out.println(i);}就可以输出2了。
第三个:1、调用test先输出try block;
        2、test函数中try中return test1();调用test1,输出return statement
            3、接下来test1中的return语句不会执行,因为执行后程序立即结束,所以先执行finally中语句,即是输出finally      block
            4、然后再执行test1中的return语句,输出after return
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马