我有以下代码。
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崩溃。据我所知。
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
答案 0 :(得分:16)
在从主块返回之前,JVM必须确保执行finally
块,因此它就是这样做的。我们的想法是执行finally
块,然后返回并执行主块中的return
语句。但是如果return
块中有finally
语句,那么它将在执行finally
块时执行...这意味着控制永远不会返回主块来完成return
声明。
return
语句。它暂停执行主块并检查finally
子句。finally
子句,包括其return
语句。try
阻止。但请注意,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
块中的代码复制一次,这会导致代码执行离开受保护的块,无论是通过return
,throw
,或跌倒。请注意,虽然某些语言不允许{/ 1}} return
块中的finally
,但Java不会;但是,如果由于异常而执行finally
块,则块中的return
可能导致异常被静默放弃(查看上面标记的代码"最后执行代码在重新投掷之前&#34 ;;如果return 3;
执行,则重新抛出将被跳过)。