第七條:避免使用終結(jié)方法(finalizer)
1. 解釋
本條的意思是恋沃,讓你盡量不要在你的類中覆蓋finalize方法丢郊,然后在在里面寫一些釋放你的類中資源的語句。
2. 為什么要避免覆蓋并使用finalize方法焰扳?
(1)finalize方法不能保證它能被及時的執(zhí)行禽捆。
(2)finalize方法甚至都不會被執(zhí)行。
(3)System.gc和System.runFinalization這兩個方法只是能增加finalize方法被調(diào)用的幾率洲炊。
(4)唯一能保證finalize方法被執(zhí)行的方法有兩個感局,System.runFinalizersOnExit和Runtime.runFinalizersOnExit但是這兩個方法已經(jīng)被棄用。
(5)覆蓋并使用終結(jié)方法會造成嚴重的性能損失暂衡。
3. 如果類中的資源確實需要被釋放询微,我們應該怎么做?
一般來說狂巢,需要釋放的資源有線程或者文件還有一下涉及到本地的資源的對象撑毛。
我們只需要提供一個public修飾的終止方法,用來釋放資源唧领,并要求這類的使用者在不再使用這個類的時候調(diào)用這個方法藻雌,并且在類中添加一個標志,來標記資源是否已經(jīng)釋放斩个,如果已經(jīng)被釋放了胯杭,那這個類中的方法如果在被調(diào)用的話就拋出IllegalStateException異常,一個很好的例子就是InputStream和OutputStream萨驶。
多說一句歉摧,在調(diào)用我們自己定義的public修飾的終止方法的時候最好和try—finally一起使用,就像下面這樣:
class MyObject{
private boolean isClosed = false;
//public修飾的終止方法
public void close(){
//資源釋放操作
...
isClosed = true;
}
}
public static void main(String... args) {
MyObject object = new MyObject();
try{
//在這里面使用object腔呜;
...
} finally {
//在這里面關(guān)閉object叁温;
object.close();
}
}
4. 什么時候使用終結(jié)方法是合理的?
(1)用終結(jié)方法充當“安全網(wǎng)”
“安全網(wǎng)”的作用是當我們提供的public修飾的終結(jié)方法被在外部忘記調(diào)用的時候提供一種安全保障核畴,如下:
class MyObject{
private boolean isClosed = false;
//public修飾的終止方法
public void close(){
//資源釋放操作
...
isClosed = true;
}
//安全網(wǎng)
@Overried
protected void finalize() throws Throwable {
try{
close();
} finally {
super.finalize();
}
}
}
(2)第二種合理用法和本地對等體相關(guān)膝但,在涉及到JNI編程的時候,我們的普通java對象有的時候需要委托給本地對象谤草,在資源回收的時候只能回收到普通java對象而回收不了被本地代碼(C或者C++)托管的對象跟束,所以需要我們在終結(jié)方法方法中通過調(diào)用本地方法來釋放掉這個被本地代碼托管的對象莺奸。
注:這種方式是面對不包含關(guān)鍵資源的對象,如果包含關(guān)鍵資源同樣需要提供一個public修飾的終結(jié)方法冀宴。
5. 在使用終結(jié)方法的時候我們應該注意些什么灭贷?
只需要注意一點,那就是確保super.finalize()方法一定會被執(zhí)行略贮。
確保它一定會被執(zhí)行的方式有兩種:
(1)使用try-finally(像上面的安全網(wǎng)一樣)甚疟;
(2)使用“終結(jié)方法守衛(wèi)”
書中的例子:
public class Foo{
//終結(jié)守衛(wèi)
private final Object finalizerGuardian = new Object{
... //釋放Foo中的資源,這里不需要調(diào)用super.finalize()
}
}
本條內(nèi)容記錄完畢逃延。