《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)有终结方法,并且子类覆盖了终结方法,子类的终结方法必须手工调用超类的终结方法。
2.采用try-finally的方式来调用超类终结方法,即使子类在终结过程中抛出异常,父类依旧可以被终结。
3.终结方法守卫者(Finalizer Guradian)。
如果子类实现者覆盖了超类的终结方法,但是忘记了调用超类的终结方法,那么超类的终结方法永远不会被调用到。防范这种情况的方法是,创建一个匿名内部类,类的终结方法写在匿名内部类(参考第22条)的方法中,这样做的代价就是为每个对象都创建了一个附加对象。
总结:
除非用作安全网,或者是为了终止非关键的本地资源,否则请不要使用终结方法。使用总结方法一定要记得调用super.finalize()。如果是用作安全网,一定要记录终结方法的非法用法。考虑使用终结方法守卫者(匿名内部类中实现终结方法),以确保子类的终结方法未能调用super.finalize()时,终结方法也会执行。
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()时,终结方法也会执行。
相关文章推荐
- extjs建立jfreechart柱状图
- AngularJS API
- JS----简单的事件委派
- 禁用iPhone手机浏览器上给电话号码自动加上的link样式
- Caffe学习(未完)
- React入门 (一) 基本语法和功能介绍
- jQuery+Ajax实现无刷新操作
- extjs表格单元双击弹窗编辑grid和form互相传值
- 将ccs导出的ExportJson文件转换成lua代码
- js前台到后台加载经典
- 清除内/外缓存,清除数据库,清除sharedPreference,清除files和清除自定义目录
- ButterKnife--View注入框架
- js offset
- jquery-ui draggable參數方法事件
- Buffer和Cache的区别
- js 浏览器滚动事件
- 青瓷引擎之纯JavaScript打造HTML5游戏第二弹——《跳跃的方块》Part 8(登陆界面)
- JS----简单的城市级联
- cJSON代码阅读(8)——解析JSON对象
- 获取css外部样式的方法及兼容代码