Java try-finally返回设计问题

时间:2010-11-15 14:36:37

标签: java

在Java中,尝试{...}终于{...}对我来说有些不直观。如另一个问题Does finally always execute in Java?所示,如果try块中有return语句,如果定义了finally块,它将被忽略。例如,函数

boolean test () {
    try {
        return true;
    }
    finally {
        return false;
    }
}

将始终返回false。我的问题:这是为什么?这个由Java做出的设计决策背后有一个特定的哲学吗?我很感激任何见解,谢谢。

编辑:我特别感兴趣的是'为什么'Java认为违反我定义的语义是可以的。如果我在try块中'返回',那么该方法应该在那里返回。但是JVM决定忽略我的指令并从一个实际上还没有 到达的子程序返回。

7 个答案:

答案 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阻止。 并警告" 最终阻止无法正常完成"

  • 只有当finallytry都没有catch语句时,
  • return阻止才会有return语句。

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

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

只有在以下情况下

finally阻止才会执行:

  • 在调用System.exit()
  • 杀戮过程
  • 应用程序/环境崩溃
  • stackoverflow /无限循环

答案 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块中重复它,并且当前代码更清晰。