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

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

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

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


当前回答

如果你只是担心记忆,那就别担心了。相信GC,它做得不错。实际上,我发现它非常高效,在某些情况下,创建一堆小对象比使用大数组的性能更好。

其他回答

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

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

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

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

尽管Java的GC技术已经有了相当大的进步,但您仍然需要注意引用。我想到了许多看起来微不足道的参考模式的例子,它们实际上是罩下的老鼠窝。

从你的文章中,听起来你并不是为了对象重用而试图实现一个reset方法(真的吗?)您的对象是否持有需要清理的其他类型的资源(例如,必须关闭的流,必须返回的任何池化或借来的对象)?如果您唯一担心的是内存dealloc,那么我将重新考虑我的对象结构,并尝试验证我的对象是自包含的结构,将在GC时被清理。

在Lombok中有一个@Cleanup注释,它与c++的析构函数非常相似:

@Cleanup
ResourceClass resource = new ResourceClass();

在处理它时(在编译时),Lombok插入适当的try-finally块,以便在执行离开变量的作用域时调用resource.close()。你也可以显式地指定另一个方法来释放资源,例如resource.dispose():

@Cleanup("dispose")
ResourceClass resource = new ResourceClass();

Java没有任何析构函数。在Java中,它背后的主要原因是垃圾收集器总是被动地在后台工作,所有对象都在堆内存中创建,这是GC工作的地方。在c++中,我们必须显式调用delete函数,因为没有垃圾收集器之类的东西。

随着Java 1.7的发布,现在有了使用try-with-resources块的额外选项。例如,

public class Closeable implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("closing..."); 
    }
    public static void main(String[] args) {
        try (Closeable c = new Closeable()) {
            System.out.println("trying..."); 
            throw new Exception("throwing..."); 
        }
        catch (Exception e) {
            System.out.println("catching..."); 
        }
        finally {
            System.out.println("finalizing..."); 
        } 
    }
}

如果执行这个类,则在try块剩余时,在catch块和finally块执行之前,将执行c.close()。与finalize()方法不同,close()保证被执行。但是,不需要在finally子句中显式地执行它。