所以我一直在經歷「Effective Java 2nd Ed。」終止一個對象是否與nulling相同?
在第7項中,他談到了不使用終結器,因爲它們會導致很多問題。
但不是使用終結器,我們可以「提供一個明確的終止方法」,這些的一個例子是close語句。我不明白什麼是「終止聲明,它們和終結器之間有什麼區別?」
我得出結論:終止一個對象就像是將它歸零,因此資源被釋放,但我想我不會明白很好。所以我感謝所有幫助的差異。
謝謝!
所以我一直在經歷「Effective Java 2nd Ed。」終止一個對象是否與nulling相同?
在第7項中,他談到了不使用終結器,因爲它們會導致很多問題。
但不是使用終結器,我們可以「提供一個明確的終止方法」,這些的一個例子是close語句。我不明白什麼是「終止聲明,它們和終結器之間有什麼區別?」
我得出結論:終止一個對象就像是將它歸零,因此資源被釋放,但我想我不會明白很好。所以我感謝所有幫助的差異。
謝謝!
,但使用的終結,我們可以「提供一個明確的 終止法」和那些的一個例子是緊密的語句。
作者引用了一個close()
方法,該方法提供了一種清理使用資源釋放對象的方法。
例如,當您創建和操縱InputStream
或OutputStream
,你不想依賴於Java終結(可能存在這些接口的一些子類。例如,它是爲FileInputStream
類的情況下定義一個finalize()
方法)來釋放與流關聯的資源,但是您想使用API提供的方法來完成它:void close()
,因爲它更可靠作爲終結器。
java.sql.Statement
作品以同樣的方式:它提供了close()
方法來釋放相關的聲明實例JDBC資源。
我得出的結論是終止一個對象就像是將其歸零 因此資源被釋放。
指定一個對象到null
不需要釋放所有應該釋放的資源。此外,如果對象或對象的字段仍然被另一個活動對象引用,則該對象將難以被垃圾收集
最後,垃圾收集可能也需要一些時間。
爲什麼要等我們不需要使用該對象?
感謝您的解釋!但我仍然不完全明白關閉和定稿之間的區別。那麼清潔對象的方法到底是什麼?我知道finalize是清理對象的垃圾回收方法。但是最終確定的方法究竟做了什麼或者不做什麼? – titorat
歡迎您.'close()'和終結器具有相同的意圖並執行相同的操作:清理並釋放對象不再需要的資源。 「我知道finalize是清理對象的垃圾回收方法」是的,但是要清理對象,你必須重寫類中的'finalize()'方法。如果您不覆蓋它,該方法什麼也不做。閱讀與以下相關的javadoc:**類Object的finalize方法不執行特殊操作;它只是通常返回**。 – davidxxx
這兩種方法之間的區別是'finalize()'可能永遠不會被調用或者調用非常晚(所以一些資源可能不會在某個延遲之前被釋放),而如果客戶端代碼顯式調用'close()'方法作爲釋放與對象關聯的資源的方法),只要返回'close()'的調用,就一定要釋放資源。 – davidxxx
顯式終止方法和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");
}
}
第一個覆蓋從Object
繼承了finalize()
方法。 Foo
和Bar
實現了由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
的Foo
的finalize()
方法被從來沒有所謂的,因爲Foo
不是垃圾收集。 JVM具有可用資源,因此爲了優化性能,它不執行垃圾收集。此外 - 如果儘管完成應用程序的事實資源不是垃圾收集。即使是第二個創建的Foo
實例也不是垃圾收集,因爲有足夠的資源讓JVM茁壯成長。
第二個與ARM是好了很多,因爲它創造了兩個資源(一個實施java.io.Closeable
和一個執行java.lang.AutoCloseable
,值得一提的是,Closeable
延伸AutoCloseable
,這就是爲什麼它是適用於ARM)。 ARM保證這些資源被關閉,當另一個拋出時關閉一個等等。第二個提供了類似於ARM的東西,但節省了大量不必要的樣板代碼。
東西讓你成爲更好的開發:
但它仍然是不完美的。程序員記住關閉對象仍然有一個負擔。 Java中沒有析構函數會迫使開發人員記住關閉資源,記得使用ARM等等。有一個很好的設計模式(由Venkat Subramaniam解釋) - Loan Pattern
。貸款模式的一個簡單的例子:
class Loan {
private Loan() {
}
public Loan doSomething(int m) {
System.out.println("Did something " + m);
if (new Random().nextBoolean()) {
throw new RuntimeException("Didn't see that commming");
}
return this;
}
public Loan doOtherThing(int n) {
System.out.println("Did other thing " + n);
return this;
}
private void close() {
System.out.println("Closed");
}
public static void loan(Consumer<Loan> toPerform) {
Loan loan = new Loan();
try {
toPerform.accept(loan);
} catch (Exception e) {
e.printStackTrace();
} finally {
loan.close();
}
}
}
您可以使用它像:
class Main {
public static void main(String[] args) {
Loan.loan(loan -> loan.doOtherThing(2)
.doSomething(3)
.doOtherThing(3));
}
}
它減輕了關閉資源的負擔開發商,因爲它已經爲他處理。如果其中一種方法拋出,則處理它,開發人員不必費心。 close方法和構造函數是私有的,不會誘使開發人員使用它們。
取消對象不會釋放任何東西。 – assylias
我想你跳過了解釋終結器用於清理非內存事物(例如打開連接,打開文件,其他系統資源)的部分。你需要做這些事情,否則你會有資源泄漏。 – RealSkeptic