Java Try-With-Resources 辩论
Posted
技术标签:
【中文标题】Java Try-With-Resources 辩论【英文标题】:Java Try-With-Resources Debate 【发布时间】:2016-04-26 16:42:51 【问题描述】:现在,在我的工作中,我们正在就资源尝试和异常抑制进行辩论。
快速回顾:从 java 7 开始,try-with-resources 消除了对关闭资源的讨厌 finally 块的需要。我个人觉得它更优雅,但我有一个不相信的同事。他不喜欢一个例外被压制,并且一直认为我们会因此而丢失信息。
起初我相信他的话,因为我是初级开发人员,他是高级开发人员,我是新人等等。但我最近发现,嘿,所有信息都进入了堆栈跟踪,包括抑制异常。所以那里不会丢失任何信息。
我正在寻找的这场辩论的最后一点(因为我提倡使用资源尝试)是自动关闭如何处理该异常。假设在尝试关闭资源时抛出异常,资源是否有可能保持打开和泄漏?最终这可能没什么大不了的,因为无论如何日志都会提醒我们这个问题。
只是好奇。非常感谢。
【问题讨论】:
那么你的问题是什么?如何说服你的同事? “假设在尝试关闭资源时抛出异常,资源是否有可能保持打开和泄漏?”它将保持开放的程度与 Java-7 之前的 try/finally 代码让它保持开放的程度完全相同。例如,我假设您没有准备好尝试多次关闭? 被抑制的异常根本不会丢失。请参阅this presentation 的幻灯片 8。 【参考方案1】:您是正确的,抑制异常不会导致信息丢失。你的同事对此的担心是没有根据的。 try-with-resources 的要点是:
确保资源被关闭,无论在使用它们时抛出什么,并且按照声明它们的相反顺序,
确保关闭时抛出的异常不会导致 try 块中抛出的异常丢失,并且
确保关闭时抛出的异常仍保留为抑制异常,因此不会丢失任何信息。
如果关闭资源引发异常,则无论哪种情况,您都无能为力。在 JDBC 中,数据库对象与数据库服务器进行通信,告诉它取消分配资源,如果关闭失败,这些对象将保持打开状态。 (无论如何,重试通常是没有意义的,因为问题通常是网络或连接发生了一些变化。)但是服务器最终会清理这些,并且它不在客户端代码的手中。 try-with-resources 和旧的 try-finally 惯用语在关闭资源方面做得同样出色,只是使用 try-finally 惯用语需要更多的工作和更多的输入。
在使用 try-with-resources 还是嵌套 try-finally 语句对我来说最大的区别是,在前一种情况下,如果 try 块中没有抛出任何东西并且在关闭时抛出了某些东西,那么在关闭时抛出异常被抛出(因为在 try 块中没有抛出异常以将其作为抑制异常附加)。如果您使用嵌套的 try-finally 块,那么您可以确保关闭时抛出的异常不会从 finally 块传播,因此释放资源时的间歇性网络故障不会导致丢失有效的业务事务。
但在实践中,很少有人能够容忍这种嵌套,并且他们采取了导致资源泄漏的捷径(通常是因为 finally 块中的早期调用失败而没有关闭的连接)。人们还倾向于编写导致异常屏蔽的代码(在第二个要点中提到),其中在关闭时抛出的异常会导致在 try 块中抛出的异常丢失; try-with-resources 可以防止这种错误。绝对有资源尝试的地方。
我的建议是尽可能多地学习异常处理,编写示例程序来演示异常是如何工作的,并了解这两种方法的优缺点,以便您可以详细讨论它们并进行比较和对比。这样,您可以表明您了解您的同事提出的担忧,并且您可以提供建议,而不是作为一种方式而不是另一种方式的倡导者,而是帮助您的团队找到帮助他们编写更好的软件的解决方案。
【讨论】:
以上是关于Java Try-With-Resources 辩论的主要内容,如果未能解决你的问题,请参考以下文章
java中的try-with-resources和return语句
道德引擎——灾难来临,你够资格登上诺亚方舟?墨尔本大学《java面向对象》结辩作业
道德引擎——灾难来临,你够资格登上诺亚方舟?墨尔本大学《java面向对象》结辩作业
道德引擎——灾难来临,你够资格登上诺亚方舟?墨尔本大学《java面向对象》结辩作业