`
RednaxelaFX
  • 浏览: 3047888 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

finally子语里的return...险恶啊

    博客分类:
  • Java
阅读更多
看看这段代码,
TestFinally.java:
public class TestFinally {
    public static void main(String[] args) {
        System.out.println(foo(-1));
        System.out.println(foo(1));
    }
    
    private static boolean foo(int value) {
        try {
            if (value < 0) {
                return false;
            } else {
                return true;
            }
        } finally {
            return false;
        }
    }
}

运行的话会看到怎样的结果呢?

D:\temp>javac TestFinally.java

D:\temp>java TestFinally
false
false


于是两次对foo()的调用都返回了false。嗯?
foo()里,控制流不是应该在try语句块里就返回了么?try里的两条分支,无论哪条应该返回才对啊?
但是同时,我们也知道finally语句块一定会在try-catch语句之后执行一次。
Java Language Specification, 3rd 写道
A finally clause ensures that the finally block is executed after the try block and any catch block that might be executed, no matter how control leaves the try block or catch block.

如果finally里的不是return那很好理解,但偏偏这里就是return语句……

Java Language Specification, 3rd里的对try-catch-finally语句执行的规定在这里。不过并没有提到return的值的问题。

唉,总之那啥……虽然很合理,但Java里的这finally子句的处理还是很诡异。居然能改写返回值,让一般的控制流与异常处理变得不怎么正交了 = =

Sun的javac从1.4.2开始就不再生成jst/ret指令来处理异常,而是直接把异常处理的代码嵌在方法里,通过异常表来确定handler的位置。
分享到:
评论
8 楼 kingquake21 2011-05-17  
	  public static void main(String[] args) {   
	      System.out.println(test()); // 1   
	      System.out.println(s_val); // 2   
	  } 
7 楼 driftcloudy 2011-04-30  
哈哈,这个问题我曾经看到过的额,帮你翻了翻

《java puzzlers》第36题

在一个 try-finally语句中,finally语句块总是在控制权离开try语句块时执行的[JLS 14.20.2]。无论try语句块是正常结束的,还是意外结束的,情况都是如此。
一条语句或一个语句块在它抛出了一个异常,或者对某个封闭型语句执行了一个 break 或continue,或是象这个程序一样在方法中执行了一个return时,将发生意外结束。它们之所以被称为意外结束,是因为它们阻止程序去按顺序执行下面的语句。 

在这个程序中,在try语句块中的 return 语句所引发的意外结束将被丢弃,而try-finally语句意外结束是由finally语句块中的return造成的。
6 楼 beneo 2011-04-29  
碰到这个问题的时候,谈求最深的一次,也就看了JLS,从来不知道
引用

jst/ret指令来处理异常,而是直接把异常处理的代码嵌在方法里,通过异常表来确定handler的位置。


对R大各种羡慕极度恨
5 楼 RednaxelaFX 2011-04-29  
Dino以前也有篇跟C#的finally相关的帖子:.NET Trivia
4 楼 raomengwen 2009-09-04  
这个讨论是什么意思啊
3 楼 RednaxelaFX 2008-05-20  
发现原来M$的Mike Stall也blog过关于C#里的return与finally的矛盾的问题:
Pop quiz: Who wins in finally vs. return?
Return vs. Finally (2)
看来C#里也是有一样的问题啊……hmm

于是回头把那边的例子换成Java试了下,行为看来一样:
public class Test {
    static int test() {
        int val = 1;
        try {
            return val;
        } finally {
            val = 2;
        }
    }

    public static void main(String[] args) {
        System.out.println(test()); // 1
    }
}


public class Test {

    static int s_val;

    static int test() {
        s_val  = 1;
        try {
            return s_val;
        } finally {
            s_val = 2;
        }
    }

    public static void main(String[] args) {
        System.out.println(test()); // 1
    }
}
2 楼 RednaxelaFX 2008-05-06  
那是啊……有记录才有积累,有积累才有进步嘛。不记下来下次又忘了 T T
1 楼 poweryoung 2008-05-06  
乃果然记下来了么...

相关推荐

Global site tag (gtag.js) - Google Analytics