finalize()
方法不像C++
中的析构,C++
中必须使用析构来释放内存和资源。在Java
中,内存通常由GC(垃圾回收器)回收,资源常采用try...finally
来完成。
使用finalize方法缺点
不能保证被执行
1). 程序被强制终结,不会调用
finalize
方法
2).finalize
方法执行时抛出异常,不会继续执行不能保证及时被执行
1). 对时间敏感的任务不能在
finalize
中执行,譬如文件资源回收性能损失
- 移植性差
1). 不同JVM
实现的GC
不同,导致finalize
在不同平台不一定都能运行
合理用途
安全网-最后释放内存和资源保障
当对象使用者忘记采用try...finaly
显示释放资源,则finalize
方法可作为最后的保障(可能释放总比不会释放要好)。譬如FileInputStram
、FileOutputStram
、Timer
、Connection
等中的finalize
方法。回收本地对等体
本地对等体:指
Java
通过JNI
调用本地方法,将普通对象委托给本地对象的对象。本地对等体不能被JVM GC
回收。当本地对等体没有关键资源时可通过
GC
回收,否则最好显示终结。
在使用finalize
方法时,需要注意的是如果子类重写了父类的finalize
方法,则子类并不会默认调用父类的finalize
方法。你需要显示的调用,如下所示:
@Override
public void finalize() throws Throwable {
try {
//子类的finalize实现
} finally {
//调用父类的finalize方法
super.finalize();
}
}
你也可以采用终结方法守卫者,代码如下:
public class Parent {
private Object finalizeGuardian = new Object() {
@Override
protected void finalize() throws Throwable {
System.out.println("Parent Guardian finalize");
}
};
private static void testFinalize() {
Sub sub = new Sub();
sub = null;
System.gc();
}
//输出结果为:
//Sub finalize
//Parent Guardian finalize
public static void main(String[] args) {
testFinalize();
}
}
class Sub extends Parent {
@Override
protected void finalize() throws Throwable {
System.out.println("Sub finalize");
}
}
总结
- 强烈不推荐使用finalize方法;
- 万一必须要使用,注意子类必须显示调用父类
finalize
方法,或采用终结方法守卫者方法