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

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

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

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


当前回答

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

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

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

其他回答

这里有很多很好的答案,但还有一些关于为什么应该避免使用finalize()的额外信息。

如果JVM由于System.exit()或Runtime.getRuntime().exit()而退出,终止器将不会默认运行。From Javadoc for Runtime.exit():

虚拟机的关闭顺序由两个阶段组成。在第一阶段,所有已注册的shutdown钩子(如果有的话)将以某种未指定的顺序启动,并允许并发运行,直到它们完成。在第二阶段中,如果启用了退出时终止,则运行所有未调用的终结器。完成此操作后,虚拟机将停止。

您可以调用System.runFinalization(),但它只会“尽最大努力完成所有未完成的终结”——并不能保证。

有一个System.runFinalizersOnExit()方法,但不要使用它——它是不安全的,很久以前就已经弃用了。

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

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

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

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

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

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

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

看看try-with-resources语句。例如:

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  System.out.println(br.readLine());
} catch (Exception e) {
  ...
} finally {
  ...
}

在这里,不再需要的资源在BufferedReader.close()方法中被释放。您可以创建自己的实现AutoCloseable的类,并以类似的方式使用它。

在代码结构方面,这个语句比finalize更有局限性,但同时它使代码更易于理解和维护。此外,也不能保证在应用程序的生存期内调用finalize方法。

我过去主要处理c++,这也是我寻找析构函数的原因。我现在经常使用JAVA。我所做的,可能对每个人来说都不是最好的,但我实现了我自己的析构函数通过将所有值重置为0或通过函数的默认值。

例子:

public myDestructor() {

variableA = 0; //INT
variableB = 0.0; //DOUBLE & FLOAT
variableC = "NO NAME ENTERED"; //TEXT & STRING
variableD = false; //BOOL

}

理想情况下,这并不适用于所有情况,但在有全局变量的情况下,只要你没有大量的全局变量,它就可以工作。

我知道我不是最好的Java程序员,但它似乎对我有用。