Java尝试最终返回设计问题

Java尝试最终返回设计问题,java,Java,在Java中,try{…}finally{…}对我来说有些不直观。如另一个问题所示,如果try块中有return语句,那么如果定义了finally块,它将被忽略。例如,函数 boolean test () { try { return true; } finally { return false; } } 将始终返回false。我的问题:为什么会这样?Java做出的这个设计决策背后是否有一种特殊的理念?我很感激你的洞察力,谢谢你

在Java中,try{…}finally{…}对我来说有些不直观。如另一个问题所示,如果try块中有return语句,那么如果定义了finally块,它将被忽略。例如,函数

boolean test () {
    try {
        return true;
    }
    finally {
        return false;
    }
}
将始终返回false。我的问题:为什么会这样?Java做出的这个设计决策背后是否有一种特殊的理念?我很感激你的洞察力,谢谢你


编辑:我对“为什么”特别感兴趣,Java认为违反我定义的语义是可以的。如果我在try块中“return”,那么该方法应该立即返回。但是JVM决定忽略我的指令,并从实际上尚未到达的子例程返回。

如果finally块中的代码突然结束,它会更改
try
块中的返回值/异常。这被认为是不好的做法,你不应该这样做


除其他地方外,本书中也讨论了这一点。

从技术上讲,如果定义了
finally
块,则try块中的
返回将不会被忽略,前提是该finally块还包含
返回

这是一个可疑的设计决策,在回顾时可能是一个错误(很像默认情况下可为空/可变的引用,并且根据一些检查异常)。在许多方面,这种行为与对
finally
意思的通俗理解完全一致——“无论
try
块中事先发生了什么,始终运行此代码。”因此,如果从
finally
块返回true,那么总体效果必须始终是返回true,不是


一般来说,这很少是一个好习惯用法,您应该大量使用
finally
块来清理/关闭资源,但很少从它们返回值。

finally
构造是JLS提供的一种工具,用于处理容易出现异常的代码。开发商可利用该设施确保从异常中顺利恢复。以您描述的方式使用
finally
构造并不是一个好的实践。因此,
从finally块返回任何内容都是不好的。

因此,正如您所说,“哲学”是处理任何突然完成的代码。如果需要返回某个值作为处理此类状态的一部分,则应在
catch
块中执行该操作。

如果使用-Xlint调用javac,则将生成一个适当的警告,指示不应从finally子句调用return。例如(使用上述
test()
方法编译一个简单类):


尽管finally块用于关闭资源,并且通常不应该有return语句,并且Eclipse警告“finally块不能正常完成”,但我发现在某些情况下,“finally return”仍然是可取的

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;
}
如果我不将return子句放在finally块中,我将不得不在try-and-catch块中重复它,当前代码会更清晰一些。

请检查此项以供参考

“带有finally块的try语句通过首先执行try块来执行。然后有一个选项:
如果try块的执行正常完成,[…]
如果try块的执行由于抛出值V而突然完成,[…]
如果try块的执行由于任何其他原因突然完成,则执行finally块。然后有一个选项:
如果finally块正常完成,则try语句由于原因R而突然完成。

如果finally块由于原因S而突然完成,则try语句由于原因S而突然完成(并且原因R被丢弃)。“

finally
的目的:

  • Java人员已经创建了用于关闭操作的
    finally
    块,这两种情况下都必须执行(例如,发生异常或无异常)

  • 不建议在
    finally
    块中使用return语句,因为它会覆盖
    catch
    &
    try
    块中的
    return
    语句。 并警告“最终块不能正常完成”

  • 只有当
    try
    catch
    都没有
    return
    语句时,
    finally
    块才应该有return语句

  • 如果
    try
    catch
    具有不同的值,那么我们不应该在
    finally
    块中保留任何内容

  • 如果我们在
    try
    catch
    块中返回相同的值,那么最好在
    finally
    中保持返回,并在
    try
    catch
    块中删除返回
  • 如果
    finally
    抛出任何异常,则该块内的
    返回将不会执行。
    

最后
块仅在以下情况下才会执行:

  • 在调用System.exit()时
  • 压井工艺
  • 应用程序/环境崩溃
  • 堆栈溢出/无限循环

一个类似的问题或有趣的事情是,如果您在最后一次尝试中没有捕获,并且您从最后一次尝试中抛出了一个异常,那么最初的异常已经进入涅盘…:)所以永远不要让例外从最后一个区块中消失不,不会的。您的代码未编译;-)@彼得:只是因为他输入了错误的返回类型。@Gábor:您可能应该从catch块抛出异常,并在捕获的异常后面附加“throw new Exception(“Message”,throwable)”,其中throwable是捕获的异常。这会给你一个很好的跟踪。但是如果在finally块中抛出异常,这听起来很奇怪,因为这意味着try块永远不会成功;-)虽然这看起来像是一个设计错误“
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;
}