我们发现经过常量池解析之后,JVM就能够确定要调用的f1()方法具体在内存的什么位置上了。实际上,这个信息在编译阶段就已经在StaticCall类的常量池中记录了下来。这种在编译阶段就能够确定调用哪个方法的方式,我们叫做静态绑定机制。
很明显,根据对象(father)的声明类型(Father)还不能够确定调用方法f1的位置,必须根据father在堆中实际创建的对象类型Son来确定f1方法所在的位置。这种在程序运行过程中,通过动态创建的对象的方法表来定位方法的方式,我们叫做动态绑定机制。(Java的动态绑定又称为运行时绑定。)
总结:
(1) 所有私有方法、静态方法、构造器及初始化方法都是采用静态绑定机制。在编译器阶段就已经指明了调用方法在常量池中的符号引用,JVM运行的时候只需要进行一次常量池解析即可。
(2) 类对象方法的调用必须在运行过程中采用动态绑定机制。
首先,根据对象的声明类型(对象引用的类型)找到“合适”的方法。具体步骤如下:
① 如果能在声明类型中匹配到方法签名完全一样(参数类型一致)的方法,那么这个方法是最合适的。
② 在第①条不能满足的情况下,寻找可以“凑合”的方法。标准就是通过将参数类型进行自动转型之后再进行匹配。如果匹配到多个自动转型后的方法签名f(A)和f(B),则用下面的标准来确定合适的方法:传递给f(A)方法的参数都可以传递给f(B),则f(A)最合适。反之f(B)最合适。
③ 如果仍然在声明类型中找不到“合适”的方法,则编译阶段就无法通过。
然后,根据在堆中创建对象的实际类型找到对应的方法表,从中确定具体的方法在内存中的位置。
http://www.cnblogs.com/devinzhang/archive/2011/12/27/2304056.html
区别对比
1.静态绑定发生在编译时期,动态绑定发生在运行时
2.使用private或static或final修饰的变量或者方法,使用静态绑定。而虚方法(可以被子类重写的方法)则会根据运行时的对象进行动态绑定。
3.静态绑定使用类信息来完成,而动态绑定则需要使用对象信息来完成。
4.重载(Overload)的方法使用静态绑定完成,而重写(Override)的方法则使用动态绑定完成。
http://developer.51cto.com/art/201201/311537.htm
如果子类Son中定义了 method() 的方法,则直接调用子类中的相应方法;如果子类Son中没有定义相应的方法,则到其父类中寻找method()方法。