天天看点

慎用Finalize方法以及Finalize方法的妙用

首先,要知道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读后感