首先,要知道finalize方法跟c++的析構函數不一樣,jvm并不保證會執行。
一、慎用finalize方法
finalize方法在什麼時候被調用:
在垃圾回收的時候,某個對象要被回收的時候,會先進行一次标記,并且将該對象的finalize放到一個低優先級的線程中去執行。
等到下一次垃圾回收的時候再把這個對象回收。
jvm并不保證在垃圾回收之前能夠執行他的finalize方法,甚至在執行finalize方法的線程發生了死循環,那其他的finalize方法都無法執行了。
二、如何替代finalize方法
使用try...finally...代碼塊,将要執行的後續操作放入到finally塊中
三、finalize方法一定沒有嗎
在一些必須要做清楚的操作中,比如說InputStream,我們都知道執行完了得把流關掉
為了避免使用者的誤操作,可以在InputStream的finalize方法中關閉流,這樣為資源的釋放增加了一層保護網,雖然不保證一定能夠執行。
四、終結方法鍊?
有些時候可能遇到這樣的情況
class Super中有一個close方法需要最後執行,是以在Super類中的finalize方法中是這樣的
@Override
protected void finalize() throws Throwable(){
this.close();
}
但是class Sub extends Super的時候,子類把Super的finalize方法給重寫了,不再調用super.finalize(),那就完蛋了,super的finalize方法肯定不會被執行了。
怎麼解決?
方法1。
@Override
protected void finalize() throws Throwable(){
try{
//finalize subclass state
}finally{
super.finalize();
}
}
當然我們并不能保證來繼承super類的人能夠這樣寫,是以有個更好的方法:
使用一個finalizerGuardian:
public class Super{
//...
private final Object finalizerGuardian=new Object(){
@Override
protected void finalize() throws Throwable(){
//Super.this.close();
}
}
}
父類被回收的時候,内部的匿名類也一定被收回,那匿名内部類的finalize方法不管子類怎麼搞都不會受影響的。是不是很巧妙。
--Effective Java讀後感