Effective Java - 创建和销毁对象 - 避免使用终结方法

读书笔记 仅供参考

Java 的终结方法和 C++ 的析构函数不是相同的事物,C++ 的析构函数可以用来回收对象所占用的资源,而 Java 有垃圾回收器自动回收。如果确实有关闭资源的需要,使用 try-finally 或 try-with-resource( Java 1.7)。

缺点一

由于 Java 的资源确定是否回收是有可达性确定(详见 Java 虚拟机),但是从一个对象不可达到终结方法执行,中间的时间是任意长的,所以不能再终极方法中关闭资源或其他注重时间的任务,否则会导致各种错误。

缺点二

如果使用了终结方法,然后在终结方法中的程序可能会抛出没有捕获的异常,按摩这种异常是不会被观测到的,警告也不会出现。而在这种情况,对象的终结过程也停止了,对象处于破坏的状态,假如此时有另一个线程企图使用这个对象,那么会发生任何不确定的行为。

缺点三

非常严重的性能损失,在作者的例子中有430倍的差距。

解决方法

如果类中的资源确实是要终止,那么好的做法是提供一个显示的终止方法,并且要求再每个实例不再有用的时候调用这个方法。
一个细节:该实例必须记录下自己是否已经被终止了
例子:InputStream 的 close() 方法。

终结方法合法用途一:安全网

当对象的使用者忘记调用显示的终结方法,终结方法可以充当安全网。迟一点释放资源总比不释放资源号。
ps:如果终结方法中发现资源没有被种子,应该在日志中记录。

终结方法合法用途二:本地对象体

本地对象体是一个本地对象,与本地方法有关。垃圾回收器不知道有本地对象的存在,所以不会被回收。在本地对象体不拥有关键资源的前提下,终结方法是终结这个本地对象体最好的工具,否则还是需要显示的终结方法。

终结方法链

终结方法链不会自动的执行,即:一个类(非 Object)有终结方法,它的子类覆盖了终结方法,那么应该显示的调用父类的终结方法(super.finalize()),最好在 finally 块中执行。如果不显示的调用,父类的终结方法永远不会被调用。
要防止上面的问题,需要为每个对象创建一个附加的对象。把终结方法放在一个匿名类中,这个匿名类的唯一作用就是终结它的外围类。匿名类的实例称为终结方法守卫者。当守卫者被终结的时候,它会执行外围实例的终结方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值