理解try catch最后返回它返回的值和值
我有以下代码。
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崩溃。 据我所知。
编辑:
(根据Dirk对此的评论)
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
在从主块返回之前,JVM必须确保执行finally
块,因此它就是这样做的。 想法是执行finally
块然后返回并从主块执行return
语句。 但是如果你在finally
块中有一个return
语句,那么它将在执行finally
块时执行…这意味着控制永远不会返回到主块来完成return
语句。
- JVM遇到主块中的
return
语句。 它暂停主块的执行并检查finally
子句。 - 它完整地执行
finally
子句,包括其return
语句。 - 它永远不会完成
try
块。
但请注意, try
块的return
表达式将被计算然后被丢弃。 如果它有副作用,这很重要。 因此,如果你的主块return i++
那么这对返回值没有影响,但i
仍然会增加。 (感谢Dirk指出这一点。)
如果你终于回来了,那就是最后的回报。
这并不奇怪。 这是实际行为。 返回值在finally
块决定。
如果你最后没有返回任何东西,那么前一个返回值的值就是返回值(在你的情况下,是try块值)。
无论你在try
中做什么,即使你从try块返回,finally块总是会执行(如果你最后返回,那就是最后的返回)。
从finally
文档
无论 try块中发生了什么,运行时系统总是执行finally块中的语句。 所以这是进行清理的最佳地点。
注意:最终设计为清理。
在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
块中的代码复制一次,这将导致代码执行离开受保护的块,无论是通过return
, throw
还是通过。 请注意,虽然某些语言不允许在 finally
块中return
,但Java不会; 但是,如果一个finally
块由于exception而被执行,则块内的return
可能导致exception被静默放弃(查看上面标记的代码“最后重新执行代码之前执行的代码”;如果return 3;
执行,重新抛出将被跳过)。