从Java中的finally块返回
最近我很惊讶地发现,在Java的finally块中可能有一个return语句。
似乎很多人都认为这是一件坏事,如"不要在finally子句中返回"中所述。更深入地研究,我还发现" Java的回报并不总是",这在finally块中显示了其他类型的流控制的一些非常可怕的示例。
因此,我的问题是,谁能给我一个示例,其中finally块中的return语句(或者其他流控制)产生更好/更易读的代码吗?
解决方案
回答
我们提供的示例足够有理由从头开始不使用流控制。
即使有一个"更好"的人为设计示例,也请考虑必须稍后维护代码并且可能不知道其细微之处的开发人员。那个可怜的开发人员甚至可能就是你。
回答
将控制结构添加并返回到finally {}块只是"只是因为我们可以"滥用的另一个示例,这些滥用实际上散布在几乎所有开发语言中。杰森(Jason)说对了,因为它很容易成为维护的噩梦,反对函数早期返回的论点更多地适用于这种情况,因此,这种情况适用于"后期返回"的情况。
最终,存在块是出于一个目的,无论我们之前的代码发生什么情况,都可以让自己彻底整理一下。原则上讲,这是关闭/释放文件指针,数据库连接等,尽管我可以看到有人说可以添加定制审核。
任何影响函数返回的内容都应放在try {}块中。即使我们有一种方法可以检查外部状态,进行耗时的操作,然后再次检查该状态(以防状态无效),我们仍然希望在try {}中进行第二次检查(如果最终位于内部),如果长时间的操作失败了,那么我们将不必要地再次检查该状态。
回答
如果使用-Xlint:finally,则javac将最终发出返回警告。如果代码有问题,最初javac不会发出警告,它应该无法编译。不幸的是,向后兼容意味着无法防止意外的愚蠢行为。
可以从finally块中引发异常,但是在那种情况下,所显示的行为几乎可以肯定是我们想要的。
回答
多年前,我很难找到一个由此引起的错误。代码类似于:
Object problemMethod() { Object rtn = null; try { rtn = somethingThatThrewAnException(); } finally { doSomeCleanup(); return rtn; } }
发生的事情是该异常已在其他一些代码中抛出。它被捕获,记录并在somethingThatThrewAnException()
方法中重新抛出。但是这个异常并没有传播到problemMethod()
之上。经过长时间的研究,我们终于将其归结为return方法。最终块中的return方法基本上是阻止try块中发生的异常传播,即使未被捕获。
就像其他人所说的那样,虽然根据Java规范从finally块返回是合法的,但这是一件不好的事情,不应该这样做。