试试这段代码。为什么getValueB()返回1而不是2?毕竟,increment()函数被调用两次。
public class ReturningFromFinally
{
public static int getValueA() // This returns 2 as expected
{
try { return 1; }
finally { return 2; }
}
public static int getValueB() // I expect this to return 2, but it returns 1
{
try { return increment(); }
finally { increment(); }
}
static int counter = 0;
static int increment()
{
counter ++;
return counter;
}
public static void main(String[] args)
{
System.out.println(getValueA()); // prints 2 as expected
System.out.println(getValueB()); // why does it print 1?
}
}
答案 0 :(得分:16)
毕竟,increment()函数被调用两次。
是的,但在第二次通话之前确定了返回值。
返回的值由在该时间点返回语句中的表达式的评估确定 - 而不是“就在执行离开方法之前”。
带有Expression的return语句尝试将控制权转移给包含它的方法的调用者; Expression的值成为方法调用的值。更准确地说,执行这样的return语句首先评估表达式。如果表达式的评估由于某种原因突然完成,则返回语句因此而突然完成。如果表达式的评估正常完成,产生值V,则return语句突然完成,原因是返回值为V.
根据section 14.20.2 of the JLS执行然后转移到finally
块。但是,这并没有在return语句中重新计算表达式。
如果您的最终阻止是:
finally { return increment(); }
那么新的返回值将是该方法的最终结果(根据第14.20.2节) - 但你没有这样做。
答案 1 :(得分:5)
请参阅my comment。
如果你有2
,它会返回finally { return increment(); }
。
在finally块之前计算第一个return
语句的表达式。请参阅Section §14.20.2 of the JLS。
如果
try
块的执行正常完成,则执行finally
块,然后有一个选择:
- 如果
finally
块正常完成,则try
语句正常完成。- 如果
finally
块突然因为S
而突然完成,则try
语句突然完成,原因为S
。
两次调用getValue2
(现在就像你一样)会导致1
后跟3
。
答案 2 :(得分:0)
finally
方法中的GetValue2
块不会返回任何内容。它只调用方法来增加counter
。
答案 3 :(得分:0)
因为在你的getValue2()方法中,你最后只是调用increment(),它不会返回它。所以你的代码正在做的是递增并返回counter(1),然后将counter递增到2,但不返回它。
答案 4 :(得分:0)
第二个示例中没有显式返回。在这种情况下,它将返回try
块内的值。它具有直观意义,因为Java
已经执行了try
块内的代码。执行finally
块后,不会再执行该块。
答案 5 :(得分:0)
finally方法的目的是确保在任何情况下都关闭资源。 考虑一下这个例子:
public List<Person> getPersons() {
Connection conn = openConnection();
try {
return selectPersons(conn);
} finally {
conn.close()
}
}
执行selectPersons(conn)后执行conn.close()语句。 否则selectPersons(conn)会引发连接关闭错误。