最近我很惊讶地发现,在Java的finally块中可以有一个return语句。
看起来很多人认为这是一件坏事,就像'Don't return in a finally clause'中描述的那样。更深入一点,我还发现了'Java's return doesn't always',它展示了一些在finally块中的其他类型的流控制的非常可怕的例子。
所以,我的问题是,有没有人给予我一个例子,在finally块中的return语句(或其他流控制)可以产生更好/更可读的代码?
最近我很惊讶地发现,在Java的finally块中可以有一个return语句。
看起来很多人认为这是一件坏事,就像'Don't return in a finally clause'中描述的那样。更深入一点,我还发现了'Java's return doesn't always',它展示了一些在finally块中的其他类型的流控制的非常可怕的例子。
所以,我的问题是,有没有人给予我一个例子,在finally块中的return语句(或其他流控制)可以产生更好/更可读的代码?
6条答案
按热度按时间6rvt4ljy1#
几年前,我很难追踪到一个由此引起的bug。代码如下:
字符串
发生的情况是,异常在其他代码中被抛出。它被捕获并记录在
somethingThatThrewAnException()
方法中并重新抛出。但异常并没有传播到problemMethod()
。经过很长时间的观察,我们最终追踪到了return方法。finally块中的return方法基本上是阻止try块中发生的异常,即使没有被发现也会继续传播就像其他人说的,虽然根据Java规范,从finally块返回是法律的,但这是一件坏事,不应该这样做。
vbopmzt12#
您提供的示例足以让
not
使用finally的流控制。即使有一个人为的例子,它是“更好”,考虑开发人员谁必须维护您的代码后,谁可能不知道的微妙之处。
myss37ts3#
如果你使用-Xlint:finally,javac会在finally返回时发出警告。最初,javac不会发出警告-如果代码有问题,它应该无法编译。不幸的是,向后兼容意味着无法禁止意想不到的巧妙愚蠢。
可以从finally块中抛出闭包,但在这种情况下,所展示的行为几乎肯定是您想要的。
siotufzp4#
在finally{}块中添加控制结构和返回值只是另一个例子,“仅仅因为你可以”滥用,几乎遍布所有开发语言。Jason说得对,这很容易成为一场维护噩梦-反对函数提前返回值的论点更适用于这种“延迟返回”的情况。
最后,块的存在有一个目的,就是让你可以完全整理自己的代码,不管前面的代码发生了什么。主要是关闭/释放文件指针,数据库连接等,尽管我可以看到它被延伸到说添加定制审计。
任何影响函数返回的东西都应该在try{}块中。即使你有一个方法,可以用来检查一个外部状态,做一个耗时的操作,然后再次检查这个状态以防它变得无效,你仍然需要在try{}中进行第二次检查-如果它位于finally{}中,并且长操作失败,那么你将不必要地第二次检查这个状态。
vptzau2j5#
一个简单的Groovy测试:
字符串
输出:
型
提问:
对我来说,一个有趣的地方是看到Groovy是如何处理隐式返回的。在Groovy中,可以从一个方法中“返回”,只是在末尾留下一个值(没有返回)。你认为会发生什么,如果你取消注解finally语句中的 runningThreads.remove(..) 行-这会覆盖常规返回值(“OK”)并覆盖异常吗?!
bpsygsoo6#
从
finally
块内部返回将导致exceptions
丢失。finally块中的return语句将导致try或catch块中可能抛出的任何异常被丢弃。
根据Java语言规范:
如果try块的执行由于任何其他原因R突然完成,那么finally块被执行,然后有一个选择:
字符串