/** 运行结果: A's constructor com.polymorphism.C com.polymorphism.C Class A null ---------------------- B's constructor com.polymorphism.C com.polymorphism.C Class B null ---------------------- C's constructor com.polymorphism.C com.polymorphism.C Class C Class C ----------------------
执行过程分析(省略Object): 1)在方法区中查找TestPoly类型信息,如果不存在,通过类加载器将TestPoly.class载入内存, 将类型信息存储到方法区中 2)将main方法入栈,开始执行main方法里面的内容 3)执行new C(),因为C从B继承,B从A继承,所以先加载A字节码,执行静态初始化和静态代码块, 将类型信息存储到方法区,接着加载B,加载A,之后根据C的类型信息计算出需要的内存大小, 为C分配堆内存空间,执行C中各成员变量默认初始化操作.调用C的构造方法,在C的构造方法中如果没有 手动指定super(参数),编译器会默认为我们加入super()来调用父类构造方法.因此会依次执行A中的 成员初始化,成员代码块,构造函数中的语句,B和C依此类推,最终完成C的初始化操作,并返回C对象的引用 此时堆中只存在C类型的对象,不会存在A,B类型的对象,不过C类型的对象中包含了A,B类型中的成员变量 C在初始化之前,已经调用了A,B的构造方法执行了父类属性的初始化操作. */ public class TestPoly { public static void main(String[] args) { new C(); } }
public class TestPoly2 { public static void main(String[] args) { Derived sub = new Derived(); // 输出1 // sub先在自己的堆空间中查找自己定义的方法签名, // 没找到再去父类型中查找,在Base中找到了show,方法的this类型为Base // 如果此时去掉Derived中show的注释,则打印出2 sub.show();