一个值得深思的问题。

 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!