Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java支持RAII/确定性销毁吗?_Java_Raii - Fatal编程技术网

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

Java支持RAII/确定性销毁吗?,java,raii,Java,Raii,我使用Java至少已经5年了,那时,每当您想要分配一个需要清理的对象(例如套接字、DB句柄)时,您必须记住添加一个finally块并在其中调用cleanup方法 相反,在C++中(或其他对象生命周期是确定性的,例如Perl),类实现器将定义析构函数,每当该类的对象超出范围时,它执行清理。这种方法的优点是,对象的用户不会忘记清理它——析构函数会被自动调用,即使抛出异常也是如此。这种方法被称为RAII——“资源获取就是初始化” 根据我的经验,以“RAII方式”做事节省了我大量的精神开销,因为我不必担

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

相反,在C++中(或其他对象生命周期是确定性的,例如Perl),类实现器将定义析构函数,每当该类的对象超出范围时,它执行清理。这种方法的优点是,对象的用户不会忘记清理它——析构函数会被自动调用,即使抛出异常也是如此。这种方法被称为RAII——“资源获取就是初始化”

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


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

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

虽然Java仍然没有提供关于最终确定时间的保证,但它确实获得了一个特性,比如C#的
使用
语句:the


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

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


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

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


如果您正在服务器上工作,可能需要签出。它与RAII无关,但它确实有一个不错的系统来管理昂贵对象(如DB连接)的生命周期。Java EE 5实际上非常适合在许多问题空间中使用。

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


有很多图书馆都这样做。在大多数情况下,你不必担心这一点。

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

它叫

有趣的是,我看到Jon Skeet插嘴了这一点,但他在这里没有提及——真为你感到羞耻,Jon——错过了在那里获得一些代表积分的机会


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

谢谢Jon。有趣的是,支持某些确定性类/对象将使确定性“感染”一切。在任何情况下,“作用域局部”的情况对我来说都很重要--“使用”是朝着正确方向迈出的一步,因为它强制析构函数的一致命名。D设法在GC上下文中进行确定性销毁,所以它可以done@Earwicker:C#以什么方式具有确定性破坏?显然。@JohnMcFarlane:我会编辑,尽管考虑到语言保证的内容与特定VM实现之间存在差异,要完全准确地做到这一点很困难。谢谢Jay。对于我们需要做的事情,JEE听起来可能有点沉重,但我会告诉其他人,看看他们怎么想。回答得很好。C++没有任何垃圾收集,但是您可以避免通过简单地在堆栈上分配来记住破坏。编译器保证无论作用域如何退出(通过正常返回或异常),都会调用析构函数。谢谢Peter,但我关心的是可靠地释放资源。我不知道如何将这一责任转移到库中——您仍然必须记住在正确的时间调用库代码。谢谢Phil,在没有确定性析构函数的情况下,这是解决问题的一个非常好的方法。不确定“nice”是否是术语,特别是在没有闭包语法的情况下——但它得到了