Java有析构函数吗?我好像找不到任何关于这个的文件。如果没有,我怎样才能达到同样的效果?

为了使我的问题更具体,我正在编写一个处理数据的应用程序,规范说应该有一个“重置”按钮,使应用程序恢复到最初的启动状态。但是,除非应用程序关闭或按下重置按钮,否则所有数据必须是“活的”。

作为一个通常的C/ c++程序员,我认为这是微不足道的实现。(因此我打算最后实现它。)我构造了我的程序,使所有“可重置”的对象都在同一个类中,这样当按下重置按钮时,我就可以销毁所有“活动”对象。

我在想,如果我所做的只是解除对数据的引用,并等待垃圾收集器收集它们,如果我的用户重复输入数据并按下重置按钮,是否会出现内存泄漏?我还在想,既然Java作为一种语言相当成熟,应该有一种方法来防止这种情况发生或优雅地解决这个问题。


当前回答

我刚刚扫描的所有答案的缺失形式是终结器更安全的替代品。关于使用try-with-resources和避免终结器,所有其他答案都是正确的,因为它们不可靠,现在已弃用……

但是他们没有提到清洁工。Java 9中添加了清洁器,以一种比终结器更好的方式显式地处理清理工作。

https://docs.oracle.com/javase/9/docs/api/java/lang/ref/Cleaner.html

其他回答

如果您正在编写Java Applet,则可以重写Applet的“destroy()”方法。它是……

*由浏览器或applet查看器调用来通知 *这个applet,它正在被回收,它应该销毁 *已分配的任何资源。stop()方法 *总是在destroy()之前被调用。

显然不是你想要的,但可能是别人在寻找的。

finalize()函数是析构函数。

但是,通常不应该使用它,因为它是在GC之后调用的,并且您无法判断何时会发生(如果有的话)。

而且,释放具有finalize()的对象需要多个GC。

您应该尝试使用try{…清理代码中的逻辑位置。最后}{…}语句!

我同意大部分答案。

你不应该完全依赖finalize或ShutdownHook

完成

The JVM does not guarantee when this finalize() method will be invoked. finalize() gets called only once by GC thread. If an object revives itself from finalizing method, then finalize will not be called again. In your application, you may have some live objects, on which garbage collection is never invoked. Any Exception that is thrown by the finalizing method is ignored by the GC thread System.runFinalization(true) and Runtime.getRuntime().runFinalization(true) methods increase the probability of invoking finalize() method but now these two methods have been deprecated. These methods are very dangerous due to lack of thread safety and possible deadlock creation.

shutdownHooks

public void addShutdownHook(Thread hook)

注册一个新的虚拟机关闭钩子。

Java虚拟机在响应两种事件时关闭:

The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown. A shutdown hook is simply an initialized but non-started thread. When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. When all the hooks have finished it will then run all uninvoked finalizers if finalization-on-exit has been enabled. Finally, the virtual machine will halt. Note that daemon threads will continue to run during the shutdown sequence, as will non-daemon threads if the shutdown was initiated by invoking the exit method. Shutdown hooks should also finish their work quickly. When a program invokes exit the expectation is that the virtual machine will promptly shut down and exit. But even Oracle documentation quoted that

在极少数情况下,虚拟机可能会中止,即停止运行而不完全关闭

这发生在虚拟机从外部终止时,例如在Unix上使用SIGKILL信号或在Microsoft Windows上使用TerminateProcess调用。如果本机方法出错,虚拟机也可能中止,例如破坏内部数据结构或试图访问不存在的内存。如果虚拟机中止,则不能保证是否会运行任何shutdown钩子。

结论:合理使用try{} catch{} finally{}块,释放finally(}块中的关键资源。在finally{}块中释放资源时,捕获Exception和Throwable。

因为Java是一种垃圾收集语言,所以您无法预测对象何时(甚至是否)会被销毁。因此没有直接等价的析构函数。

有一个被称为finalize的继承方法,但它完全由垃圾回收器自行调用。因此,对于需要显式清理的类,约定是定义一个close方法,并仅使用finalize方法进行完整性检查(即,如果close未被调用,则立即执行并记录错误)。

最近有一个问题引发了关于finalize的深入讨论,所以如果需要的话,应该会提供更多的深度……

我完全同意其他答案,说不依赖执行的最后确定。

除了try-catch-finally块,还可以使用Runtime#addShutdownHook(在Java 1.3中引入)在程序中执行最后的清理。

这与析构函数不同,但是可以实现一个关机钩子,该钩子具有注册的侦听器对象,可以调用清理方法(关闭持久数据库连接、删除文件锁等)——这些事情通常在析构函数中完成。 同样,这不是析构函数的替代品,但在某些情况下,您可以使用它来实现所需的功能。

这样做的好处是使解构行为与程序的其余部分松散耦合。