有没有C++ Java 中的析构函数等效吗?
最简单的设计如下:
class Session {
Timer t = new Timer();
// ...
};
每当分配 Session
时,我都会在其中启动一个计时器;计时器将在 10-20 分钟后到期。现在,假设 Session
在计时器到期之前被销毁;那么这是我必须停止计时器的情况。我不知道是否有最后一个方法在 Session
被销毁时总是被调用。
Java 中是否有某种相当于 C++ 析构函数的东西,可以帮助我在 Session
被销毁时 cancel()
计时器? (无需等待 GC)
编辑:请不要重新标记 C++。我想要类似的东西。 Session
是一个电话会话,当连接到它的所有用户都断开连接时,该会话就会被销毁。现在,没有最后调用的 Session
方法,也没有任何异常。
In simplest form, following is the design:
class Session {
Timer t = new Timer();
// ...
};
Whenever, Session
is allocated, I start a timer inside it; the timer will be expired after 10-20 mins. Now, suppose if Session
is destroyed before the timer can expire; then it's a scenario where I must stop timer. I don't know if is there any last method which is always called when Session
is destroyed.
Is there some sort of C++ destructor equivalent in Java, which help me to cancel()
the timer when Session
is destroyed ? (without waiting for GC)
Edit: Please don't retag for C++. I wanted something of that equivalent. The Session
is a phone session which is get destroyed when all the user connected to it are disconnected. Now, there is no Session
method which is called lastly nor there is any exception.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
不,Java 中没有内置这样的东西。最接近的是编写一个终结器,但不能保证它会运行。
Session是如何被销毁的?如果有调用的方法,请务必将代码放在那里。
如何创建会话?如果您在 try/catch 块中执行此操作,则可以清理 finally 块中的所有内容。
我会编写一个 close() 方法来处理它并在 finally 块中调用它。
No, there's no such thing built into Java. The closest is to write a finalizer, but there's no guarantee that it'll run.
How is a Session destroyed? If there's a method called, by all means put the code there.
How do you create a Session? If you do it within a try/catch block, you can clean up everything in a finally block.
I would write a close() method that took care of it and call it in a finally block.
与 C++ 不同,您无法控制 Java 中的对象释放 - 也就是说,GC 在认为合适的时候收集对象,只是保证它不会收集在给定时间范围内的任何引用可以到达的任何对象。
有
Object.finalize()
,它充当执行清理的最后机会钩子,但运行时根本不保证它会被调用。我会重新考虑设计并尝试想出一种更明确的方法来清理计时器。
Unlike C++, you cannot control object deallocation in Java - that is, the GC collects objects whenever it sees fit, merely guaranteeing that it won't collect anything that can be reached through any reference that is in scope at a given time.
There is
Object.finalize()
, which acts as a last-chance hook to do cleanup, but the runtime does not guarantee that it gets called at all.I'd rethink the design and try to come up with a more explicit way of cleaning up your timers.
在 Java 中,变量并不像在 C++ 中那样直接表示对象 - Java 中的变量是对对象的引用。因此,对象不能超出范围 - 只有引用对象的变量才能超出范围。
您可以重写 Finalize(),它是 Object 类中的一个方法,当垃圾收集器要永久丢弃对象时会调用该方法,但这与析构函数并不完全相同。请参阅 Object 类中的 Finalize() 方法的 API 文档。
In Java, variables do not directly represent objects like they do in C++ - variables in Java are references to objects. So an object cannot go out of scope - only a variable that refers to an object can go out of scope.
You can override finalize(), which is a method in class Object that is called by the garbage collector when it is about to permanently discard an object, but that's not exactly the same as a destructor. See the API documentation of the finalize() method in class Object.
首先,
finalize
不相当于析构函数。不要尝试将其作为一个整体来使用;这是行不通的。 Java 中没有为此构建任何内容,但在某些圈子中,有一个约定使用void dispose()
来实现此目的;您可以编写ptr.dispose(),而不是
delete ptr;
。 (当然,内存稍后会被回收。)在这种情况下,最好还定义finalize
,以便在dispose< 之前回收对象时生成某种内部错误。 /code> 被调用。
First,
finalize
is not the equivalent of a destructor. Don't try and use it as one; it won't work. There is nothing built into Java for this, but in some circles, there is a convention to usevoid dispose()
for this; instead ofdelete ptr;
, you writeptr.dispose()
. (The memory, of course, gets reclaimed later.) In such cases, it's a good idea to also definefinalize
, to generate some sort of internal error if the object is reclaimed beforedispose
is called.大多数时候,您可以构建问题,因此不需要析构函数。
为每个Session创建一个Timer是比较重的。您最好向 ScheduledExecutorService 提交延迟任务。通过使其重量轻,就没有必要取消它。 (事实上,cancel() 不会删除它,它被标记为不运行)
在这种情况下,为了简单起见,您可以使用单例 ScheduledExecutorService。
这里昂贵的组件 ScheduledExecutorService 被创建一次并在应用程序的生命周期内存在。当 Session 被清理(且任务已过期)时,Future 被丢弃
Most of the time you can structure the problem so you don't need a destructor.
Creating a Timer for each Session is relatively heavy weight. You are better off submitting a delay task to a ScheduledExecutorService. By making it light weight there would be no need to cancel it. (In fact cancel() doesn't remove it, it is flagged not to run)
You can have a singleton ScheduledExecutorService for simplicty in this case.
Here the expensive component, the ScheduledExecutorService is created once and lives for the life of the application. The Future is discarded when the Session is cleaned up (and the task has expired)
java中没有这样的方法。当对象被垃圾收集器销毁时,可能会调用在顶级
Object
中定义的finalize()
方法,但这不是您可以执行的行为依靠。您能做的最好的事情就是将对象设置为 null(删除引用),这将使其为垃圾回收做好准备。
There is not a method like that in java. The
finalize()
method, defined in the top-levelObject
, may be invoked when the object is being destroyed by the garbage collector, but this is not a behavior you can rely upon.The best you can do is just set the object to null (removes the reference), which will make it ready for garbage collection.
您可以使用 CDI(上下文依赖注入) - 例如 Weld,或者在某些 JEE 服务器(TomEE、JBoss 等)上运行程序。下面是一个使用数据库的示例。
根据您的喜好,在您的类上使用适当的 @...Scoped (ApplicationScoped、SessionScoped 等)注释,例如:
在用 @PostConstruct 注释的某些方法的构造函数中执行您想要执行的操作:
使用 @Inject 注释将您的对象注入到其他位置(如果您愿意):
清理、销毁对象并断开与数据库的连接 - 您想在 C++ 的析构函数中在注释的方法中执行的操作和MyDatabaseFactory 类的 @PreDestroy,例如:
使用起来非常简单,我们在 Java 中拥有相当于 C++ 中的析构函数。
You may use CDI (Context Dependency Injection) - such as Weld for example or run the program on some JEE server (TomEE, JBoss etc.). Below you have an example of working with databases.
Use appropriate @...Scoped (ApplicationScoped, SessionScoped etc.) annotation on your class, as you prefer eg.:
Do what you wanted to do in constructor in some method annotated with @PostConstruct:
Inject your object with @Inject annotation to other places (if you want to):
Cleanup, destroy objects and disconnect from database - what you wanted to do in destructor from C++ in method annotated with @PreDestroy of MyDatabaseFactory class, eg.:
It is very simple to use and we have in Java equivalent of destructor from C++.