目录
一、静态绑定
1、含义
又称前期绑定,在编译时就已经确定所要调用的方法是哪一个,由编译器或者其他连接程序实现。
2、使用范围
在java中,只有final,static,private以及构造函数是静态绑定的。
二、动态绑定
1、含义
又称后期绑定,在运行时才判断所引用对象的实际类型,根据其实际类型调用相应的方法。
2、使用范围
在java中,除了final,static,private以及构造函数之外的所有方法都是动态绑定的。
3、分析
之所以需要动态绑定,是因为一个方法在继承链中可能会有多个实现(子类对父类方法的重写),而父类句柄又能够引用子类对象。
例:Father是Son的父类,Son中重写了Father的talk()方法。在main中,使用Father句柄去引用一个Son的对象,然后在调用talk()方法,这是就会出现一个分歧:到底是调用Father的talk()还是Son的talk()?根据接下来要讨论的动态绑定原则可知,会调用Son的实现。
public class Father {
public void talk() {
System.out.println("I am father. ");
}
}
public class Son extends Father {
@Override
public void talk() {
System.out.println("I am son. ");
}
public void run() {
System.out.println("I can run. ");
}
}
public class Demo {
public static void main(String[] args) {
Father somebody = new Son();
somebody.talk();
}
}

此外,值得注意的是,尽管运行阶段调用的是Son的talk()实现,但在编译阶段,编译器会在Father类中去寻找talk()方法,所以如果想利用父类句柄调用子类中父类所不具有的方法是不行的,例如此例中somebody调用run()方法是不行的。

4、动态绑定的原则
假设object属于class A,而class A在如图所示的继承链当中,则当object调用某个方法Fun()时,JVM就会在继承链上从class A开始向上查找到最近的Fun()的实现(或者理解为直接调用class A对Fun()的实现,这里将class A中没有实现视作直接继承了父类中对Fun()的实现),然后调用之,即理论上会调用class C重写的Fun()(注意这里的class B是对Fun()的重载,会被看作是另一个方法)。

实际测试:
public class D {
public void print() {
System.out.println("print D");
}
}
public class C extends D {
@Override
public void print() {
System.out.println("print C");
}
}
public class B extends C {
public void print(String str) {
System.out.println("print B");
}
}
public class A extends B {
}
public static void main(String[] args) {
D d = new A();
d.print();
}

参考链接:
https://baijiahao.baidu.com/s?id=1670567662304221792&wfr=spider&for=pc
https://blog.youkuaiyun.com/weixin_42247720/article/details/80450238