Welcome

首页 / 软件开发 / JAVA / java继承和finalize()

java继承和finalize()2007-05-28 yycnet.yeah.net yyc译通过“合成”方法创建新类时,永远不必担心对那个类的成员对象的收尾工作。每个成员都是一个独立的对象,所以会得到正常的垃圾收集以及收尾处理——无论它是不是不自己某个类一个成员。但在进行初始化的时候,必须覆盖衍生类中的finalize()方法——如果已经设计了某个特殊的清除进程,要求它必须作为垃圾收集的一部分进行。覆盖衍生类的finalize()时,务必记住调用finalize()的基础类版本。否则,基础类的初始化根本不会发生。下面这个例子便是明证:
//: Frog.java// Testing finalize with inheritanceclass DoBaseFinalization {public static boolean flag = false;}class Characteristic {String s;Characteristic(String c) {s = c;System.out.println("Creating Characteristic " + s);}protected void finalize() {System.out.println("finalizing Characteristic " + s);}}class LivingCreature {Characteristic p = new Characteristic("is alive");LivingCreature() {System.out.println("LivingCreature()");}protected void finalize() {System.out.println("LivingCreature finalize");// Call base-class version LAST!if(DoBaseFinalization.flag)try {super.finalize();} catch(Throwable t) {}}}class Animal extends LivingCreature {Characteristic p = new Characteristic("has heart");Animal() {System.out.println("Animal()");}protected void finalize() {System.out.println("Animal finalize");if(DoBaseFinalization.flag)try {super.finalize();} catch(Throwable t) {}}}class Amphibian extends Animal {Characteristic p = new Characteristic("can live in water");Amphibian() {System.out.println("Amphibian()");}protected void finalize() {System.out.println("Amphibian finalize");if(DoBaseFinalization.flag)try {super.finalize();} catch(Throwable t) {}}}public class Frog extends Amphibian {Frog() {System.out.println("Frog()");}protected void finalize() {System.out.println("Frog finalize");if(DoBaseFinalization.flag)try {super.finalize();} catch(Throwable t) {}}public static void main(String[] args) {if(args.length != 0 &&args[0].equals("finalize")) DoBaseFinalization.flag = true;elseSystem.out.println("not finalizing bases");new Frog(); // Instantly becomes garbageSystem.out.println("bye!");// Must do this to guarantee that all // finalizers will be called:System.runFinalizersOnExit(true);}} ///:~

DoBasefinalization类只是简单地容纳了一个标志,向分级结构中的每个类指出是否应调用super.finalize()。这个标志的设置建立在命令行参数的基础上,所以能够在进行和不进行基础类收尾工作的前提下查看行为。
分级结构中的每个类也包含了Characteristic类的一个成员对象。大家可以看到,无论是否调用了基础类收尾模块,Characteristic成员对象都肯定会得到收尾(清除)处理。
每个被覆盖的finalize()至少要拥有对protected成员的访问权力,因为Object类中的finalize()方法具有protected属性,而编译器不允许我们在继承过程中消除访问权限(“友好的”比“受到保护的”具有更小的访问权限)。
在Frog.main()中,DoBaseFinalization标志会得到配置,而且会创建单独一个Frog对象。请记住垃圾收集(特别是收尾工作)可能不会针对任何特定的对象发生,所以为了强制采取这一行动,System.runFinalizersOnExit(true)添加了额外的开销,以保证收尾工作的正常进行。若没有基础类初始化,则输出结果是:
not finalizing basesCreating Characteristic is aliveLivingCreature()Creating Characteristic has heartAnimal()Creating Characteristic can live in waterAmphibian()Frog()bye!Frog finalizefinalizing Characteristic is alivefinalizing Characteristic has heartfinalizing Characteristic can live in water

从中可以看出确实没有为基础类Frog调用收尾模块。但假如在命令行加入“finalize”自变量,则会获得下述结果:
Creating Characteristic is aliveLivingCreature()Creating Characteristic has heartAnimal()Creating Characteristic can live in waterAmphibian()Frog()bye!Frog finalizeAmphibian finalizeAnimal finalizeLivingCreature finalizefinalizing Characteristic is alivefinalizing Characteristic has heartfinalizing Characteristic can live in water

尽管成员对象按照与它们创建时相同的顺序进行收尾,但从技术角度说,并没有指定对象收尾的顺序。但对于基础类,我们可对收尾的顺序进行控制。采用的最佳顺序正是在这里采用的顺序,它与初始化顺序正好相反。按照与C++中用于“破坏器”相同的形式,我们应该首先执行衍生类的收尾,再是基础类的收尾。这是由于衍生类的收尾可能调用基础类中相同的方法,要求基础类组件仍然处于活动状态。因此,必须提前将它们清除(破坏)。