问题描述
- 一个值得深思的问题。
-
public class FinallyTest { public int test() { int i = 0; try { i++; return i; } finally { i--; } } public static void main(String[] args) { System.out.println(new FinallyTest().test()); ; } }
碰到一个问题:
自己分析: finally块应该是在return之前执行吧。
Debug调试发现,当执行到return i;时,下一步执行 finally块。
然后 到 return i;这行。i的值虽然i--了,但还是没执行finally块前的值。。
表述可能不清,可运行下看看。
我有点不明白其中的执行过程。
解决方案
是这样的,函数的返回值是return i;决定的。注意,这里return i;其实是对i求值之后记录下返回值,在函数返回的时候返回。
固然i--;会改变i,但是返回值此时已经确定了。
public int test() {
int i = 0;
try {
i++;
return i;
} finally {
i--;
return i;
}
}
这样写返回0,因为返回值被再次刷新了。
你可以把return il看成如下代码
[result] = i;
[result]是一个编译器产生的隐含变量
你的程序其实是
public int test() {
int i = 0;
try {
i++;
[result] = i;
} finally {
i--;
}
}
解决方案二:
这需要从虚拟机角度考虑,编译器使用异常表而不是简单的跳转命令来实现Java异常及finally处理机制。简单的说就是,编译后的字节码,会将return语句的返回值保存到栈,然后再执行finally,由于return的值在finally之前已经保存在栈中,所以不管finally怎么更改,都不会改变return的值
解决方案三:
@ caozhy
caozhy 讲的不错
解决方案四:
caozhy 说的是对的,返回的值已经确定了
解决方案五:
这个属于java语言的天生的缺陷,不要深思,更不要卖弄。
eclipse中建议直接在:项目/属性/java编译/警告错误中
将
finally block does not complete normally
设置为error!
解决方案六:
一个值得程序员深思的问题
值得深思的问题
值得深思的問題
时间: 2024-09-21 21:44:20