先看代码

    1. class Parent {
    2. Parent() {
    3. System.out.println("开始父类的无参构造");
    4. draw();
    5. System.out.println("结束父类的无参构造");
    6. }
    7. void draw() {
    8. System.out.println("父类的 draw 方法");
    9. }
    10. }
    11. class Child extends Parent {
    12. private int radius = 1;
    13. Child(int r) {
    14. System.out.println("开始子类的构造");
    15. radius = r;
    16. System.out.println("结束调用子类的构造, radius=" + radius);
    17. }
    18. void draw() {
    19. System.out.println("调用子类的 draw 方法,radius=" + radius);
    20. }
    21. public static void main(String[] args) {
    22. new Child(100);
    23. }
    24. }
    25. ==========控制台==========
    26. 开始父类的无参构造
    27. 调用子类的 draw 方法,radius=0
    28. 结束父类的无参构造
    29. 开始子类的构造
    30. 结束调用子类的构造, radius=100

    疑问1:
    为什么在构造方法中可以调用到该类的普通方法?不应该是构造函数执行完毕后该对象才算创建完成,才能使用其属于对象的普通方法吗?
    我的猜想:
    对象的创建完成,包括两部分,一是该对象的类已经加载进内存,二是数据已经初始化完成。其实当执行构造方法时,说明该类已经加载完毕(类只加载一次),此时,在构造方法中仅仅是做一些显示的初始化而已。当在构造方法中调用普通方法时,由于该数据已经加载进了内存,所以是可以调用的,只是还未做显示的数据初始化而已。

    疑问2:
    为什么在继承树追溯的过程中,父类构造方法中调用了子类重写过的方法,会执行子类重写的方法,而不是父类自己的方法,此时子类对象还并未创建啊?(注意,这里说的是继承树追溯的过程中,不是指子类已经创建完毕,因向上转型而出现的多态的特性)
    我的猜想:
    如果我疑问1的猜想成立,那么这个就很好解释了。首先,程序运行时类已经加载进了内存,只要加载进内存的数据,符合访问控制权限,就可以访问到,而构造方法只是对其做显示的初始化而已。
    继承树追溯的过程,就是把父类对象中非私有数据(非private修饰)+ 非构造方法 的所有数据复制给子类对象而已,这样就达到了代码复用的目的。即,继承树追溯的过程,就是将父类的数据复制给子类对象的过程。因为整个追溯过程都是为了创建子类对象,所以当父类构造方法中调用被子类重写过的方法时,理应体现出子类的特性。

    拓展:
    如果父类对象的构造方法中调用了子类重写的方法,由上面的分析可知,会执行子类中的该方法,但是,此时的子类还未显式初始化,成员变量都是默认初始化值。那么子类重写的该方法中使用了子类的成员变量的某些方法,就会报空指针异常。