构造方法的调用顺序:子类构造器中,JVM会自动的先调用父类的构造方法,然后再执行子类构造方法。在JVM自动调用父类构造方法的时候,会完成父类中拥有的成员变量的值的初始化操作,此时子类的成员变量并未初始化,java中基本类型都会使用JVM给定的默认值(如int为0),只有当父类构造方法调用结束,并到执行子类构造器时才会进行子类成员变量的初始化过程。
动态绑定:对于非private、static、final修饰的方法,JVM是在运行期间,用函数指针指向实习对象类型的方法。比如,子类重写了父类的A方法,使用父类Upper的引用upper指向了子类Sub对象,然后upper.A(),实际调用的类Sub中A方法。我是这样理解的,子类和父类中都有方法A,并且子类是通过重写的方式实现了A,所以子类对象原本Upper中指向方法A的指针和Sub类中指向A的指针是通过同一个函数指针,两次赋值。就是指针point值被替换了,不是把父类的函数指针隐藏了,而是相当于两次给指针赋值,第一次使用父类A方法的指针赋给point,第二次使用子类A方法的指针赋给point(以上纯属自己的理解,如果不真确欢迎给位老师指点,因为自己还是刚入行)。所以每一父类的方法的地址被子类方法的地址替换了。
demo:
Upper Code:
1 package com.hq.dynamicBind; 2 3 public class Upper { 4 5 private int i = 1; 6 7 public void print(){ 8 System.out.println("i="+i); 9 } 10 11 public Upper(){ 12 System.out.println("父类构造函数开始"); 13 System.out.println("i="+i); 14 print(); 15 System.out.println("父类构造函数嗲用print()结束"); 16 i = 30; 17 } 18 }
Sub Code:
1 package com.hq.dynamicBind; 2 3 public class Sub extends Upper { 4 5 private int j = 20; 6 7 public void print() { 8 System.out.println("j="+j); 9 } 10 11 public Sub(){ 12 System.out.println("成员变量j="+j); 13 print(); 14 j = 40; 15 } 16 17 }
Client Code:
1 package com.hq.dynamicBind; 2 3 public class Client { 4 5 public static void main(String[] args ){ 6 new Sub().print(); 7 } 8 }
执行结果:
父类构造函数开始
i=1
父类构造函数嗲用print()结束
成员变量j=20
j=20
j=40