首页 文章

理解try catch最后返回它返回的值和值

提问于
浏览
8

我有以下代码 .

public static void main(String[] args) {
    System.out.println(returnString());
}
private static String returnString(){
    try {
        System.out.println("Executing try");
        return "Return try value";
    } catch (Exception e){
        System.out.println("Executing Catch");
        return "Return catch value";
    } finally {
        System.out.println("Executing finally");
        return "Return finally value";
    }
}

这个输出是

Executing try
Executing finally
Return finally value

如果我改变我的finally块而不返回任何类似的东西

public static void main(String[] args) {
    System.out.println(returnString());
}
private static String returnString(){
    try {
        System.out.println("Executing try");
        return "Return try value";
    } catch (Exception e){
        System.out.println("Executing Catch");
        return "Return catch value";
    } finally {
        System.out.println("Executing finally");
    }
}

然后输出是

Executing try
Executing finally
Return try value

现在我明白了,除非我们调用system.exit(0),否则最终总会被执行;调用或JVM崩溃 . 我无法理解的是为什么返回值已经改变了?我仍然希望它返回try块的值 .
任何人都可以解释为什么最终值被考虑而不是try块的返回值?

Please refrain from answering because finally is executed even if there is an return in try block ... or finally doesn't execute only if there is a system.exit(0); called or the JVM crashes. as I know that.

编辑:

(根据Dirk评论this

public static void main(String[] args) {
    System.out.println(returnString());
}
private static String returnString(){
    try {
        System.out.println("Executing try");
        return printString("Return try value");
    } catch (Exception e){
        System.out.println("Executing Catch");
        return printString("Return catch value");
    } finally {
        System.out.println("Executing finally");
        return printString("Return finally value");
    }
}

private static String printString(String str){
    System.out.println(str);
    return str;
}

输出:

Executing try
Return try value
Executing finally
Return finally value
Return finally value

3 回答

  • 16

    就在从主块返回之前,JVM必须确保执行 finally 块,所以它就这样做了 . 想法是执行 finally 块然后返回并从主块执行 return 语句 . 但是如果 finally 块中有 return 语句,那么它将在执行 finally 块时执行...这意味着控制永远不会返回主块来完成 return 语句 .

    • JVM遇到主块中的 return 语句 . 它暂停执行主块并检查 finally 子句 .

    • 它完整地执行 finally 子句,包括其 return 语句 .

    • 永远不会完成 try 块 .

    但请注意, try 块的 return 表达式将被计算然后被丢弃 . 如果它有副作用,这很重要 . 因此,如果你的主块有 return i++ ,那么这对返回值没有影响,但是 i 仍然会增加 . (感谢Dirk指出这一点 . )

  • 2

    If you have return in finally, that's the final return.

    这并不奇怪 . 这是实际行为 . 返回值在 finally 块决定 .

    如果你最后没有返回任何东西,那么前一个返回值的值就是返回值(在你的情况下,是try块值) .

    无论你在 try 做什么,即使你从你的try块返回,finally块总是会执行(如果你最后返回,那就是最后的返回) .

    来自finally docs

    运行时系统始终执行finally块中的语句,而不管try块中发生了什么 . 所以这是进行清理的最佳地点 .

    注意:最终设计为清理 .

  • 2

    在Java中,代码:

    try {
      if (foo()) return 1;
    } catch (Exception e){
      if (goo()) return 2;
    } finally {
      if (moo()) return 3;
    }
    

    将由编译器重写为:

    try {
      if (foo())
      {
        if (moo()) return 3;  // Finally code executed before return
        return 1;
      }
    } catch (Exception e){
      if (goo())
      {
        if (moo()) return 3;  // Finally code executed before return
        return 2;
      }
    } catch (Throwable e){
      if (moo()) return 3;   // Finally code executed before re-throw
      throw e;
    }
    if (moo()) return 3;    // Finally code executed before leaving block
    

    基本上,编译器将在每个执行路径中复制 finally 块中的代码一次,这将导致代码执行离开受保护的块,无论是通过 returnthrow 还是直通 . 请注意,虽然某些语言不允许在 finally 块中使用 return ,但Java不会;但是,如果由于异常而执行了 finally 块,则块内的 return 可能导致异常被静默放弃(查看上面标记为"Finally code executed before re-throw"的代码;如果 return 3; 执行,则重新抛出将被跳过) .

相关问题