我一直在阅读很多关于finalize()的Java新手问题,并发现没有人真正清楚地表明finalize()是一种不可靠的清理资源的方法,这有点令人困惑。我看到有人评论说他们用它来清理连接,这真的很可怕,因为唯一接近于保证连接关闭的方法是最后实现try (catch)。

我没有学过CS,但我已经用Java专业编程近十年了,我从来没有见过有人在生产系统中实现finalize()。这并不意味着它没有用处,或者和我一起工作的人一直在做正确的事情。

所以我的问题是,实现finalize()有哪些用例不能通过语言中的另一个进程或语法更可靠地处理?

请提供具体的场景或您的经验,简单地重复Java教科书,或最终确定的预期用途是不够的,因为这不是这个问题的意图。


当前回答

作为旁注:

覆盖finalize()的对象由垃圾回收器进行特殊处理。通常,在对象不再在作用域中后,在收集周期中立即销毁对象。但是,可终结对象被移到队列中,在队列中,独立的终结线程将耗尽队列并在每个对象上运行finalize()方法。一旦finalize()方法终止,对象就可以在下一个循环中进行垃圾收集了。

源代码:finalize()在java-9上已弃用

其他回答

Finalize()对于捕获资源泄漏非常有用。如果资源应该关闭,但没有关闭,则将资源未关闭的事实写入日志文件并关闭。通过这种方式,您可以删除资源泄漏,并提供一种方法来知道它已经发生,以便您可以修复它。

我从1.0 alpha 3(1995)开始就一直在用Java编程,我还没有覆盖任何东西的finalize…

删除已经添加到全局/静态位置(不需要)的东西,并在对象被删除时需要删除,这是很方便的。例如:

    private void addGlobalClickListener() {
        weakAwtEventListener = new WeakAWTEventListener(this);

        Toolkit.getDefaultToolkit().addAWTEventListener(weakAwtEventListener, AWTEvent.MOUSE_EVENT_MASK);
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();

        if(weakAwtEventListener != null) {
            Toolkit.getDefaultToolkit().removeAWTEventListener(weakAwtEventListener);
        }
    }

我不知道你是怎么想的,但是…

itsadok@laptop ~/jdk1.6.0_02/src/
$ find . -name "*.java" | xargs grep "void finalize()" | wc -l
41

所以我猜《太阳报》找到了一些(他们认为)应该使用它的案例。

iirc——你可以使用finalize方法作为实现昂贵资源池机制的一种手段——这样它们就不会得到GC了。

自1998年以来,我一直在从事Java专业工作,但我从未实现过finalize()。一次也没有。