Java在try-catch-finally机制中的返回值

Ver*_*ern 13 java jvm coding-style

我刚刚遇到以下代码:

public class TestFinally {
    public static void main(String[] args) {
        int returnValue = function();

        System.out.println("Return value: " + returnValue);
    }

    public static int function() {
        try {
            return 1;
        } catch (Exception e){
            return 2;
        } finally{
            return 3;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

毫无疑问,运行此代码将产生"返回值:3"的输出.

但是,我很好奇:

  1. JVM中内部机制.有没有人知道VM是否实际上通过覆盖第一个"返回1"来替换堆栈上的返回值?如果是这样,我在哪里可以找到更多相关信息.
  2. 我还没有找到在这种方式使用的finally机制中返回的用法,并允许在JVM中实现.如果使用此代码构造作为返回错误代码的方法,我认为有更好的方法来记录错误或返回这些错误代码.有没有人发现这种结构的用途?

提前谢谢了.

干杯,Vern

Rob*_*bin 13

我在Java语言规范中发现的至少定义了你的代码片段应该返回3.当然,它没有提到JVM应该如何实现它,以及可以做什么样的优化.

14.20.2节定义了这一点

如果try块的执行由于任何其他原因R突然完成,则执行finally块.然后有一个选择:

  1. 如果finally块正常完成,则try语句突然完成,原因是R.
  2. 如果finally块由于原因S而突然完成,则try语句突然完成,原因S(并且原因R被丢弃).

第14章的开头(更准确的是第14.1节)规定了正常和突然完成的内容.例如return,具有给定值的a是突然完成.

因此,在这种情况下,finally块突然完成(原因:return具有给定值),因此try将以相同的原因突然完成(并返回3).这是在证实有关return语句段14.17以及

如果表达式的评估正常完成,产生值V,则return语句突然完成,原因是返回值为V.


Sav*_*era 5

FWIW,我收到了关于功能的警告:

public static int function(){
    try{
        return 1;
    }catch(Exception e){
        return 2;
    }finally{
        return 3; //WARNING on this line
    }
}
Run Code Online (Sandbox Code Playgroud)

IE浏览器.它告诉我"最后块没有正常完成".无论如何,我仍然得到3作为返回值.

无论如何,如果我尝试另一个例子:

public class TestFinally {
    public static void main(String[] args) {
        int returnValue = function();

        System.out.println("Return value: " + returnValue);
    }

    public static int function() {
        try {  

            return 1;  
            }  
        catch (Exception e) {   
            return 2;  
            }  
        finally {  
            System.out.println("i don't know if this will get printed out.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出将(显然)

i don't know if this will get printed out.
Return value: 1
Run Code Online (Sandbox Code Playgroud)

我不知道JVM是如何实现它的,但是查看它的最简单方法(至少在概念上)将是:

  1. "try"中的返回值被压入堆栈,
  2. 然后执行"finally"块,
  3. 新的返回值被压入堆栈
  4. 函数退出,并从堆栈中弹出返回值,从而忽略第一个.

确实很整洁的问题.