您的位置:首页 > Web前端

《Effective java》读书记录-第7条-避免使用终结方法

2016-01-04 16:37 399 查看
终结方法带来的问题:

1.终结方法( finalizer)通常是不可预测的,也是很危险的,一般情况下是不必要的。使用终结方法会导致行为不稳定、降低性能,以及可移植性问题。当然,终结方法也有其可用之处,但我们还是应该避免使用。

终结方法的缺点在于不能保证会被及时的执行。

2.不要被System.gc和System.runFinalization这两个方法所诱惑,它们确实增加了终结方法被执行的机会,但它们并不保证终结方法一定会被执行。

3.使用终结方法会有非常严重的性能损失。会增加对象创建和销毁的时间(大约430倍,原作者机器的性能)

终结方法合理用法:

1.充当“安全网”。

当对象的所有者忘记调用显示终止方法时,保证对象能够被释放(晚释放总比不释放好)。

FileInputStream、FileOutputStream、Timer和Connection这四个类都具有终结方法,当它们的终止方法未被调用时,这些终结方法就充当了安全网。

2.与本地对等体(native peer)有关。

本地对等体是一个本地对象,本地代码是java方法的实施是由并非java代码提供。在定义一个native method时,并不提供实现体(有些像定义一个java interface),因为其实现体是由非java语言在外面实现的,所以垃圾回收器不知道本地对等体的存在。

注意

1.“终结方法链(finalizer chaining)”并不会被自动执行。如果类(不是Object)有终结方法,并且子类覆盖了终结方法,子类的终结方法必须手工调用超类的终结方法。

public class Parent {

@Override
protected void finalize() throws Throwable {
try {
System.out.println("parent finalize ");
}finally {
super.finalize();
}
}
}
public class Son extends Parent {

@Override
protected void finalize() throws Throwable {
try {
System.out.println("son finalize");
}finally {
super.finalize();
}

}
}

2.采用try-finally的方式来调用超类终结方法,即使子类在终结过程中抛出异常,父类依旧可以被终结。

3.终结方法守卫者(Finalizer Guradian)。

如果子类实现者覆盖了超类的终结方法,但是忘记了调用超类的终结方法,那么超类的终结方法永远不会被调用到。防范这种情况的方法是,创建一个匿名内部类,类的终结方法写在匿名内部类(参考第22条)的方法中,这样做的代价就是为每个对象都创建了一个附加对象。

//Finalizer Guardian idiom
private final Object finalizeGuardian =new Object() {
@Override
protected void finalize() throws Throwable {
//Finalizer outer Parent object
try {
System.out.println("parent finalize Guardian");
}finally {
super.finalize();
}
}
//Remainder omitted
};


总结:

除非用作安全网,或者是为了终止非关键的本地资源,否则请不要使用终结方法。使用总结方法一定要记得调用super.finalize()。如果是用作安全网,一定要记录终结方法的非法用法。考虑使用终结方法守卫者(匿名内部类中实现终结方法),以确保子类的终结方法未能调用super.finalize()时,终结方法也会执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: