在Java中,尝试{...}终于{...}对我来说有些不直观。如另一个问题Does finally always execute in Java?所示,如果try块中有return语句,如果定义了finally块,它将被忽略。例如,函数
boolean test () {
try {
return true;
}
finally {
return false;
}
}
将始终返回false。我的问题:这是为什么?这个由Java做出的设计决策背后有一个特定的哲学吗?我很感激任何见解,谢谢。
编辑:我特别感兴趣的是'为什么'Java认为违反我定义的语义是可以的。如果我在try块中'返回',那么该方法应该在那里返回。但是JVM决定忽略我的指令并从一个实际上还没有 到达的子程序返回。
答案 0 :(得分:37)
从技术上讲,如果return
块定义,则不会忽略try块中的finally
,前提是该finally块还包含{{1 }}
这是一个可疑的设计决策可能回想起来的错误(很像默认情况下引用是可空/可变的,并且根据一些情况,检查异常)。在许多方面,这种行为与对return
意味着什么的口语理解完全一致 - “无论事先在finally
块中发生什么,总是运行此代码。”因此,如果try
阻止return true
,那么整体效果必须始终为true,不是吗?
一般来说,这很少是一个很好的习惯用法,你应该大量使用finally
块来清理/关闭资源,但很少从它们返回一个值。
答案 1 :(得分:2)
如果finally块中的代码突然结束,则会更改try
块的返回值/异常。这被认为是不好的做法,你不应该这样做。
在其他地方,这也在Java Puzzlers书中讨论过。
答案 2 :(得分:1)
如果使用-Xlint调用javac,则会生成相应的警告,指示不应从finally子句调用return。例如(使用上面的test()
方法编译一个简单的类):
javac -Xlint foo.java
foo.java:13: warning: [finally] finally clause cannot complete normally
}
^
1 warning
答案 3 :(得分:0)
finally
构造是JLS提供的一种工具,用于处理容易出现异常的代码。开发人员可以利用此工具确保从异常中恢复正常。以你所描述的方式使用finally
结构并不是一个好的做法。就此而言,{finally}块中return
的任何东西永远都不是好事
所以当你使用asekd时,“哲学”将处理任何突然完成的代码。如果需要返回某个值作为处理这种状态的一部分,那应该在catch
块内完成。
答案 4 :(得分:0)
查看此内容以供参考 Does finally always execute in Java?
“首先执行try块,执行带有finally块的try语句。然后有一个选择:
如果try块的执行正常完成,[...]
如果try块的执行由于抛出值V而突然完成,[...]
如果try块的执行由于任何其他原因R突然完成,则执行finally块。然后有一个选择:
如果finally块正常完成,则try语句突然完成,原因为R
如果finally块因为S而突然完成,则try语句突然完成,原因是S(并且原因R被丢弃)。“
答案 5 :(得分:0)
finally
的目的:
Java人员已经为关闭操作创建了finally
块,必须在两种情况下执行(例如发生异常或无例外)。
建议不要在finally
块中使用return语句,因为它会覆盖来自return
&的catch
语句。 try
阻止。
并警告" 最终阻止无法正常完成"
finally
和try
都没有catch
语句时, return
阻止才会有return语句。
如果try
和catch
有不同的值,那么我们就不应该在finally
块中保留任何内容,
try
和catch
块中返回相同的值,则最好在finally
中保持返回并删除try
和&中的返回值catch
阻止。finally
抛出任何异常,则该块内的return
将不会执行。
finally
阻止才会执行:
答案 6 :(得分:-1)
尽管finally块是用于关闭资源的,并且返回语句通常不应该存在,但Eclipse警告"最后块不能正常完成",我在某些情况下发现& #34;最后回归"仍然是可取的。
ResponseType response = new ResponseType();
try{
//set some properties of the response object.
response.setStatus(1);
//return response;
}catch (Exception e){
//Some other properties of the response object according to the exception.
response.setStatus(0);
//return response;
}finally{
return response;
}
如果我没有将finally子句放在finally块中,我将不得不在try和catch块中重复它,并且当前代码更清晰。