简体   繁体   English

Java是否支持RAII /确定性破坏?

[英]Does Java support RAII/deterministic destruction?

It's been at least 5 years since I worked with Java, and back then, any time you wanted to allocate an object that needed cleaning up (eg sockets, DB handles), you had to remember to add a finally block and call the cleanup method in there. 自从我使用Java以来​​已经至少5年了,当时,只要你想分配一个需要清理的对象(例如套接字,数据库句柄),你必须记住添加一个finally块并调用清理方法在那里。

By contrast, in C++ (or other languages where object lifetimes are deterministic, eg Perl), the class implementor would define a destructor function that performs the cleanup whenever an object of that class goes out of scope. 相比之下,在C ++(或其他对象生命周期是确定性的语言,例如Perl)中,类实现者将定义一个析构函数,只要该类的对象超出范围,该函数就会执行清理。 The advantage of this approach is that the user of the object can't forget to clean it up -- the destructor gets called automatically, even if an exception is thrown. 这种方法的优点是对象的用户不会忘记清理它 - 即使抛出异常,也会自动调用析构函数。 This approach goes by the fairly awful name of RAII -- "Resource Acquisition Is Initialisation". 这种方法以RAII的相当可怕的名字命名 - “资源获取是初始化”。

It's been my experience that doing things "the RAII way" has saved me a lot of mental overhead in terms of not having to worry about whether and when resource deallocations occur. 根据我的经验,做“RAII方式”的事情在不必担心是否以及何时发生资源解除分配方面为我节省了大量精神开销。 We are considering using Java for a medium-sized project, and I'm wondering if some sort of deterministic destruction is among the many new features added to the language since I last looked at it. 我们正在考虑将Java用于一个中型项目,我想知道自从我上次查看它以来,语言中添加的许多新功能是否存在某种确定性破坏。 (I'm hopeful as my complaint that "Java has no RAII" was rebuked on this thread , but so far I haven't been able to find any details by googling.) (我希望因为我的抱怨“Java没有RAII” 在这个帖子上被斥责,但到目前为止我还没能通过谷歌搜索找到任何细节。)

So if someone could point me to some introductory material on how to go about this in Java that would be great! 所以,如果有人能够指出一些关于如何在Java中实现这一目标的介绍性材料,那就太棒了!

EDIT: The answer below was written in early 2009, when Java 7 was very much still in flux. 编辑:下面的答案写于2009年初,当时Java 7仍然处于不稳定状态。

While Java still doesn't provide guarantees around finalization timing, it did gain a feature like C#'s using statement: the try-with-resources statement . 虽然Java仍然无法提供有关最终化时序的保证,但它确实获得了像C#的using语句这样的功能: try-with-resources语句


No, Java hasn't changed at all in that respect. 不,Java在这方面根本没有改变。 You still need to use try/finally. 你仍然需要使用try / finally。

There's been discussion of adding the equivalent of C#'s "using" statement (which is syntactic sugar over try/finally) to Java, but I don't think that's going to be part of Java 7 any more. 有人讨论过将相当于C#的“using”语句(这是语法糖而不是try / finally)添加到Java中,但我不认为它将再次成为Java 7的一部分。 (Most of the language improvements seem to have been dropped.) (大多数语言改进似乎已被删除。)

It's worth understanding that there are reasons why deterministic destruction hasn't been implemented in Java and .NET in the form of a reference-counted garbage collector, by the way - that a) impacts performance and b) fails with circular references. 值得理解的是,为什么在Java和.NET中没有以引用计数的垃圾收集器的形式实现确定性破坏,顺便说一句 - a)影响性能,b)通过循环引用失败。 Brian Harry wrote a detailed email about this - it's about .NET and it's rather old, but it's well worth a close read. Brian Harry写了一篇关于这个的详细电子邮件 - 它是关于.NET的,而且相当陈旧,但值得仔细阅读。

There is a pattern that helps here. 有一种模式可以帮助到这里。 It's not as nice as destructor based RAII but it does mean that the resource clean-up can be moved to the library (so you can't forget to call it). 它不如基于析构函数的RAII那么好,但它确实意味着资源清理可以移动到库中(所以你不能忘记调用它)。

It's called Execute Around, and has been discussed here before . 它被称为Execute Around,之前已在此讨论过

Interestingly I see Jon Skeet chimed in on that thread, but he didn't mention it here - shame on you Jon - missed an opportunity for some rep points there! 有趣的是,我看到Jon Skeet在那个帖子中插话,但是他没有在这里提到它 - 对你的羞耻乔恩 - 错过了那里的一些回复点的机会!

BTW, while I'm glad Brian Harry (see Jon's comment, again) went to the lengths of writing the email that he did - and it obviously did reflect a lot of thought that went into the process - and I'm glad we did get "using" out of it in C# - I don't agree with all his conclusions. 顺便说一句,虽然我很高兴Brian Harry(再次看到Jon的评论)写了他写的电子邮件的长度 - 这显然反映了很多进入这个过程的想法 - 我很高兴我们做到了在C#中“使用”它 - 我不同意他的所有结论。 In particular, I don't see why, if we can have using, we can't have a way to mark a type as behaving that way without "using". 特别是,我不明白为什么,如果我们可以使用,我们就没有办法将类型标记为没有“使用”的行为。 Of course it constrains the usage - but so does "using" - and most of the time it's exactly what you want. 当然它限制了使用 - 但“使用”也是如此 - 而且大部分时间它都是你想要的。 The trouble with "using" is that the client code still has to remember to use it. “使用”的麻烦在于客户端代码仍然需要记住使用它。 With C++ style RAII it's a property of the type. 使用C ++风格的RAII,它是该类型的属性。 An arguably bigger problem with "using", or more accurately with the Dispose idiom, is that it's a lot more complicated and error prone than most people realise to get right - mostly because of the potential for objects to be brought back from the dead. “使用”或者更准确地说使用Dispose惯用语这个可以说是更大的问题是,它比大多数人认为要做到的更复杂和容易出错 - 主要是因为物体可能从死亡中被带回来。

Nope. 不。 There is no facility for allocating Objects on the stack. 没有用于在堆栈上分配对象的工具。 Every Object is allocated on the heap and can outlive whatever block it was initialized in. Or it may be collected mid-block, depending on the vagaries of the all mighty Garbage Collector. 每个对象都在堆上分配,并且可以比它初始化的任何块寿命更长。或者它可以在块中间收集,这取决于所有强大的垃圾收集器的变幻莫测。

If you're working on the server, you might want to check out Java EE . 如果您正在使用服务器,则可能需要查看Java EE It has nothing to do with RAII, but it does have a decent system for managing the life cycles of expensive objects like DB connections. 它与RAII无关,但它确实有一个很好的系统来管理像DB连接这样的昂贵对象的生命周期。 Java EE 5 is actually pretty nice to work with for a lot of problem spaces. Java EE 5实际上很适合处理很多问题空间。

The approach I take is to use a layered product (sometime a simple static method) which takes care of the resource allocation. 我采用的方法是使用分层产品(有时是简单的静态方法)来处理资源分配。 You don't want this sort of resource allocation littering your program. 您不希望这种资源分配乱丢您的程序。

There are plenty of libraries which do this. 有很多库可以做到这一点。 It not something you should have to worry about in most cases. 在大多数情况下,这不是你应该担心的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM