终止一个对象是否与归零一样?

时间:2017-06-05 14:07:55

标签: java oop effective-java

所以我一直在经历" Effective Java 2nd Ed。"

在第7项中,他谈到不使用终结器,因为它们可能会导致很多问题。

但我们可以"而不是使用终结器。提供明确的终止方法"其中一个例子就是密切的陈述。我不明白什么是"终止语句和它们与终结者之间的区别是什么?

我得出结论,终止一个对象就像归零一样,因此资源被释放。但我想我不太了解它的区别。所以我感谢任何帮助。

谢谢!

2 个答案:

答案 0 :(得分:8)

  

但我们可以“提供一个明确的,而不是使用终结器   终止方法“和那些例子是密切的陈述。

作者提到了一种close()方法,该方法提供了一种清理使用资源释放的对象的方法。

例如,当您创建和操作InputStreamOutputStream时,您不希望依赖Java终结器(可能存在这些接口的某些子类。例如,它是定义FileInputStream方法的finalize()类的情况,以释放与流关联的资源,但您希望使用API​​提供的方法来执行此操作:void close()因为它是终结者更可靠。

java.sql.Statement以相同的方式工作:它提供close()方法来释放与语句实例关联的JDBC资源。

  

我得出结论,终止一个对象就像归零一样   因此资源被释放。

将对象分配给null将不必释放应该释放的所有资源。此外,如果对象或对象的一个​​字段仍被另一个生物对象引用,则该对象将难以被垃圾收集。

最后,收集垃圾可能还需要一段时间 如果我们不需要使用该对象,为什么还要等待?

答案 1 :(得分:1)

显式终止方法和finalize()之间的主要区别在于第二个不能保证被调用。它最终在垃圾收集期间被调用,这可能是诚实的,从未发生过。让我们考虑以下三个类。

class Foo {
    @Override
    public void finalize() {
        System.out.println("Finalize Foo");
    }
}

class Bar implements Closeable {
    @Override
    public void close() {
        System.out.println("Close Bar");
    }
}

class Baz implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("Close Baz");
    }
}

第一个覆盖从finalize()继承的Object方法。 FooBar实现由ARM(自动资源管理)处理的两个接口。

Foo foo = new Foo();
new Foo();
try (Bar bar = new Bar(); Baz baz = new Baz()) { // this is ARM 
    System.out.println("termination example");
}
Bar bar = null;
try {
    bar = new Bar();
    // ...
} finally {
    if (bar != null) {
        bar.close();
    }
}

此示例应返回:

termination example
Close Baz
Close Bar
Close Bar

finalize()的{​​{1}}方法永远不会被调用,因为Foo不是垃圾回收。 JVM具有可用资源,因此对于性能优化,它不执行垃圾收集。此外 - 如果资源不是垃圾收集,尽管完成应用程序的事实。即使是第二个创建的Foo实例也不是Garbage Collected,因为有足够的资源让JVM蓬勃发展。

第二个使用ARM的方法要好得多,因为它创建了两个资源(一个实现Foo,一个实现java.io.Closeable,值得一提的是java.lang.AutoCloseable扩展{{1} },这就是为什么它可用于ARM)。 ARM保证这两种资源都要关闭,当另一种抛出时关闭一个等等。第二个类似于ARM,但节省了大量不必要的样板代码。

让您成为更好的开发者的东西:

但它仍然不完美。程序员仍然有责任记住关闭对象。 Java中没有析构函数会迫使开发人员记住关闭资源,记得使用ARM等等。有一个很好的设计模式(很好地解释了Venkat Subramaniam) - Closeable。贷款模式的一个简单例子:

AutoCloseable

你可以这样使用它:

Loan Pattern

它减轻了开发人员关闭资源的负担,因为它已经为他处理了。如果这些方法中的一个抛出,则处理它并且开发人员不必费心。 close方法和构造函数是私有的,不会诱使开发人员使用它们。