
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
终结方法(finalizer)通常是不可预测的,也是很危险的,一般情况下是不必要的.
使用终结方法会导致行为不稳定,降低性能,以及可移植性问题.
不要把finalizer当成是C++中的析构器(destructors)的对应物.
在Java中,当一个对象变得不可到达的时候,垃圾回收器会回收与该对象相关联的存储空间.
C++的析构器也可以用来回收其他的非内存资源,而在Java中,一般用try-finally块来完成类似的工作.
终结方法的缺点在于不能保证会被及时地执行.从一个对象变得不可到达开始,到它的终结方法被执行,所花费的时间是任意长的. JVM会延迟执行终结方法.
及时地执行终结方法正是垃圾回收算法的一个主要功能.这种算法在不同的JVM上不同.
Java语言规范不仅不保证终结方法会被及时地执行,而且根本就不保证它们会被执行.所以不应该依赖于终结方法来更新重要的持久状态.
不要被System.gc()和System.runFinalization()这两个方法所迷惑,它们确实增加了终结方法被执行的机会,但是它们并不保证终结方法一定会被执行.
如果未捕获的异常在终结过程中被抛出来,那么这种异常可以被忽略,而且该对象的终结过程也会终止.
使用终结方法有一个严重的性能损失.
如果类的对象中封装的资源(例如文件或线程)确实需要终止,应该怎么做才能不用编写终结方法呢?只需提供一个显式的终止方法.并要求该类的客户端在每个实例不再有用的时候调用这个方法.注意,该实例必须记录下自己是否已经被终止了,如果被终止之后再被调用,要抛出异常.
例子: InputStream, OutputStream和java.sql.Connection上的close()方法; java.util.Timer的cancel()方法.
Image.flush()会释放实例相关资源,但该实例仍处于可用的状态,如果有必要会重新分配资源.
显式的终止方法通常与try-finally块结合使用,以确保及时终止.
终结方法的好处,它有两种合法用途:
当显式终止方法被忘记调用时,终结方法可以充当安全网(safety et).但是如果终结方法发现资源还未被终止,应该记录日志警告,这表示客户端代码中的bug.
对象的本地对等体(native peer),垃圾回收器不会知道它,当它的Java对等体被回收的时候,它不会被回收.如果本地对等体拥有必须被及时终止的资源,那么该类就应该有一个显式的终止方法,如前,可以是本地方法或者它也可以调用本地方法;如果本地对等体并不拥有关键资源,终结方法是执行这项任务最合适的工具.
注意,终结方法链(finalizer chaining)并不会自动执行.子类覆盖终结方法时,必须手动调用超类的终结方法. try中终结子类, finally中终结超类.
为了避免忘记调用超类的终结方法,还有一种写法,是在子类中写一个匿名的类,该匿名类的单个实例被称为终结方法守卫者(finalizer guardian),当守卫者被终结的时候,它执行外围实例的终结行为.这样外围类并没有覆盖超类的终结方法,保证了超类的终结方法一定会被执行.
了解详情请登陆昆明达内IT培训官网(km.tedu.cn)!