本帖最后由 秦冲 于 2012-5-29 12:49 编辑
- public class Test {
- public static void main(String[] args) {
- System.out.println("return value of getValue(): " + getValue());
- }
- public static int getValue() {
- try {
- return 0;
- } finally {
- return 1;
- }
- }
- }
复制代码 执行结果:return value of getValue(): 1 - public class Test {
- public static void main(String[] args) {
- System.out.println("return value of getValue(): " + getValue());
- }
- public static int getValue() {
- int i = 1;
- try {
- return i;
- } finally {
- i++;
- }
- }
- }
复制代码 执行结果:return value of getValue(): 1 - public class Test {
- public static void main(String[] args) {
- System.out.println(test());
- }
- public static String test() {
- try {
- System.out.println("try block");
- return test1();
- } finally {
- System.out.println("finally block");
- }
- }
- public static String test1() {
- System.out.println("return statement");
- return "after return";
- }
- }
复制代码执行结果 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;
|