代码之家  ›  专栏  ›  技术社区  ›  j_random_hacker

Java支持RAII/确定性销毁吗?

  •  34
  • j_random_hacker  · 技术社区  · 15 年前

    我使用Java至少已经5年了,那时,每当您想要分配一个需要清理的对象(例如套接字、DB句柄)时,您必须记住添加一个 finally 块并调用其中的清理方法。

    根据我的经验,以“RAII方式”做事节省了我大量的精神开销,因为我不必担心是否以及何时发生资源分配。我们正在考虑在一个中等规模的项目中使用Java,我想知道自从我上一次研究它以来,在该语言添加的许多新特性中是否有某种确定性的破坏。(我满怀希望,因为我的抱怨“Java没有RAII”遭到了指责 on this thread ,但到目前为止,我还无法通过谷歌搜索找到任何细节。)

    所以,如果有人能给我指一些关于如何在Java中实现这一点的介绍性材料,那就太好了!

    4 回复  |  直到 7 年前
        1
  •  30
  •   Jon Skeet    5 年前

    编辑:下面的答案是在2009年初写的,当时Java7仍在不断变化。

    虽然Java仍然没有提供关于最终确定时间的保证,但它 using 声明:委员会 try-with-resources statement .


    不,Java在这方面没有任何变化。您仍然需要使用try/finally。

    有人讨论过在Java中添加C#的“using”语句(这是try/finally的语法糖分),但我认为这不会成为Java7的一部分。(大部分语言改进似乎都被放弃了。)

    值得一提的是,Java和.NET中没有以引用计数垃圾收集器的形式实现确定性销毁,这是有原因的——a)影响性能,b)循环引用失败。布莱恩·哈里写了一篇文章 detailed email 关于这一点——它是关于.NET的,它相当古老,但它非常值得仔细阅读。

        2
  •  10
  •   Community Egal    7 年前

    这里有一种模式很有用。它不如基于析构函数的RAII好,但它确实意味着可以将资源清理移到库中(因此您不能忘记调用它)。

    它叫 Execute Around, and has been discussed here before .

    顺便说一句,虽然我很高兴布莱恩·哈利(再次看到乔恩的评论)像他那样写了这么长的电子邮件——这显然反映了在这个过程中的很多想法——我很高兴我们在C#中确实“使用”了它——但我不同意他的所有结论。特别是,我不明白为什么,如果我们可以使用,我们就不能在没有“使用”的情况下将类型标记为以这种方式运行。当然,它限制了使用——但“使用”也是如此——而且大多数时候,它正是你想要的。“使用”的问题在于客户端代码仍然必须记住使用它。使用C++样式RAII是类型的属性。“使用”,或者更准确地说,Dispose成语的一个可以争议的更大问题是,它比大多数人意识到的要复杂得多,而且容易出错——这主要是因为可能会有物体从死亡中复活。

        3
  •  2
  •   Burkhard    8 年前

    不。没有在堆栈上分配对象的工具。每个对象都是在堆上分配的,并且可以比它初始化时所在的块更有效。或者它可以在块中间收集,这取决于全能垃圾收集器的变幻莫测。

    Java EE . 它与RAII无关,但它确实有一个不错的系统来管理昂贵对象(如DB连接)的生命周期。JavaEE5实际上非常适合在很多问题空间中使用。

        4
  •  -1
  •   Peter Lawrey    15 年前

    我采用的方法是使用分层产品(有时是一种简单的静态方法),它负责资源分配。你不想让这种资源分配乱丢你的程序。

    有很多图书馆都这样做。在大多数情况下,这不是你应该担心的事情。