继承关系中子类与父类加载与初始化

  前面一篇文章说了类初始化的过程,本篇说说继承关系中类的加载与初始化。

 首先抛出一个问题,Student s = new Student();总共做了哪些事?
 1、加载Student.class文件进内存,
 2、如果Student有父类,则递归加载父类class文件并进行初始化;注意Student实现接口并不会加载和初始化。
 3、初始化Student该类,初始化过程参考之前文章讲解。
 4、父类递归进行成员变量的默认初始值设置。
 5、Student进行成员变量默认初始值设置。(现在博主不知道这个动作是JAVA虚拟机做的还是在编译器自动添加的)
 6、递归进行对父类成员变量进行显示初始值设置包括代码块。
 7、对Student进行成员变量显示初始值设置包括代码块。
 8、递归调用父类的构造方法。注意:这里是因为java编译器在Student的所有构造器里面必须强制显示或者隐示调用父类某一个构造器,这是JAVA的特性,即希望在构造器完成必要的初始值设置,同时子类需要使用父类的值时可以调用。
 9、Student调用构造方法对学生对象的成员变量赋值。
 10、学生对象初始化完毕,把对象地址赋值给s变量。

以下介绍一个例子:

public class PloyConstructors {
    public static void main(String[] args) {
        new RoundGlayph(5);
    }
}
class Glyph{
    void draw(){
        System.out.println("Glyph().draw");
    }
    Glyph(){
        draw();
    }
    {
        System.out.println("Glyph");
    }
}

class RoundGlayph extends Glyph{
    private int i = 1;
    private String a ;
    {
        System.out.println("RoundGlayph");
    }
    RoundGlayph(int r){
        a = "123";
        System.out.println("before RoundGlayph(),i="+i);
        i = r;
        System.out.println("after RoundGlayph(),i="+i);
    }
    void draw() {
        System.out.println("RoundGlayph().drwa(),i="+i);
//System.out.println("RoundGlayph().drwa(),i="+i+a.toString());  //这样a还没有初始化,报空指针
    }
}

 为什么调用a.toString()会报错相信我们应该懂了,但是现实中如果解决这个事情呢,TIJ一书说到,最好是不要这样做,即父类不要调用子类重写的方法,如果你真要这样做的话,就可以在使用时判断是否初始化。

你可能感兴趣的:(java)