我刚刚遇到以下代码:
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;
}
}
}
毫无疑问,运行此代码将产生“返回值:3”的输出。
然而,我很好奇:
非常感谢提前。
干杯, 韦恩
答案 0 :(得分:13)
我在Java语言规范中发现的至少定义了你的代码片段应该返回3.当然,它没有提到JVM应该如何实现它,以及可以做什么样的优化。
第14.20.2节定义了
如果由于任何其他原因导致try块的执行突然完成,则执行finally块。然后有一个选择:
- 如果finally块正常完成,则try语句突然完成,原因是R。
- 如果finally块因为S而突然完成,则try语句突然完成,原因为S(并且原因R被丢弃)。
醇>
第14章的开头(section 14.1更精确)指明了正常和突然完成的内容。例如,具有给定值的return
是一个突然完成。
因此,在这种情况下,finally
块突然完成(原因:return
具有给定值),因此try
将因相同原因突然完成(并返回3) 。这在section 14.17 about the return statement以及
如果表达式的评估正常完成,产生值V,则return语句突然完成,原因是返回值为V.
答案 1 :(得分:5)
FWIW,我收到了关于功能的警告:
public static int function(){
try{
return 1;
}catch(Exception e){
return 2;
}finally{
return 3; //WARNING on this line
}
}
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.");
}
}
}
输出将(显然)
i don't know if this will get printed out.
Return value: 1
我不知道JVM是如何实现它的,但最简单的方法是查看它(至少在概念上):
确实非常简洁。
答案 2 :(得分:4)
实现取决于JVM,并且有许多JVM。你可以深入研究OpenJDK's source code以了解它如何实现finally
,但这不是唯一的方法。就语言而言,重要的是行为。
我不明白第2点 - 为什么finally
存在?它并不像你建议的那样只是一种返回错误代码的方法。你根本不必从finally
内返回。该构造的存在是为了确保在某些代码段之后运行某种类型的清理代码,无论它是如何终止的,无论是正常的还是通过异常或返回。
答案 3 :(得分:0)
完全解释页面:439 => http://docs.oracle.com/javase/specs/jls/se8/jls8.pdf
如果表达式的评估正常完成,则生成一个 值V,然后return语句突然完成,原因是返回 值V。
前面的描述说“试图转移控制”而不仅仅是“转移” 控制“因为如果方法或构造函数中有任何try语句(§14.20) 其try块或catch子句包含return语句,然后是finally语句 这些try语句的子句将按顺序在最里面到最外面执行 控制权转移给方法或构造函数的调用者。 突然完成了 finally子句可以中断由return语句启动的控制转移。