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

时间:2014-10-30 16:52:33

标签: java return return-value try-catch-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");
        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块的返回值吗?

请不要回答,因为即使在try块中有返回,最终也会执行...或者最终只有在有system.exit(0)时才执行;调用或JVM崩溃。据我所知。

编辑:

(根据Dirkthis评论)
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 个答案:

答案 0 :(得分:16)

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

  1. JVM遇到主块中的return语句。它暂停执行主块并检查finally子句。
  2. 它完整地执行finally子句,包括其return语句。
  3. 永远不会完成try阻止。
  4. 但请注意,try阻止return表达式的评估然后被丢弃。如果它有副作用,这很重要。因此,如果您的主要区块有return i++,那么这对返回值没有影响,但i仍会增加。 (感谢Dirk指出这一点。)

答案 1 :(得分:2)

如果你最后回来了,那就是最终的回归。

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

如果你最后没有返回任何内容,那么前一个值将成为返回值是返回值(在你的情况下,是try块值)。

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

来自finally docs

  

运行时系统始终执行finally块中的语句,无论是否在try块中发生。因此,它是进行清理的理想场所。

注意:最终设计为清理。

答案 2 :(得分: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,或跌倒。请注意,虽然某些语言不允许{/ 1}} return块中的finally ,但Java不会;但是,如果由于异常而执行finally块,则块中的return可能导致异常被静默放弃(查看上面标记的代码"最后执行代码在重新投掷之前&#34 ;;如果return 3;执行,则重新抛出将被跳过)。