【JAVA】动态绑定与静态绑定
【JAVA】动态绑定与静态绑定
Sarzn什么是动态绑定和静态绑定?
绑定(Build)
先说什么是绑定
绑定(Binding)就是:方法调用和方法实现之间建立联系的过程。
简单来说但你调用a.eat()
这个方法的时候,程序要知道你具体调用的是哪段代码
这个寻找具体调用的段代码的过程,就叫做绑定
一个程序想要”跑”起来,需要经过两个阶段,先编译后运行
在编译过程中就确认了具体用哪个方法就叫静态绑定 在运行过程中才确认用哪个方法就叫动态绑定
静态绑定
程序在
编译阶段就能确定使用那个方法
类型: 通过下面关键词修饰的方法是静态的,子类无法对父类的方法进行重写
- static 方法,静态方法
- private 方法,私有方法
- final 方法,被 final 修饰不能被重写
- 构造方法
- 通过 super().xxx 调用的方法
为什么这些是静态绑定? 因为它们都有一个共同点:不能被子类重写,或者调用方式跟对象的实际类型无关。既然不存在”多个版本”的可能性,编译器自然在编译时就能拍板。
1 | class Animal { |
像程序一样思考 >这里的 a.info() 方法被调用了,
>先看引用类型是 Animal, >进入 Animal 看 info 方法, >哦,发现被
static 修饰所以是静态方法.直接确定了就是这个函数
>用这个函数返回 我是动物
注意!!
在 java 中成员变量也是静态绑定 1
2
3
4
5
6
7
8
9
10
11
12
13
14class Animal {
String name = "动物";
}
class Dog extends Animal {
String name = "狗";
}
public class Main {
public static void main(String[] args) {
Animal a = new Dog();
System.out.println(a.name); // 输出:动物 ← 不是"狗"!
}
}
输出动物,而不是狗,因为成员变量是静态绑定 >这就告诉我们在写 java 的时候,最好不要在子类和父类中定义相同的成员变量.容易引发误解
又一个注意!
成员变量确实是静态绑定的,但是如果只有父类有这个成员变量的话,那自然也就调用父类这个成员变量,
比如: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class Animal {
String name;
public Animal(String name) {
this.name = name;
}
}
class Dog extends Animal {
public Dog(String name) {
super.(name);
}
}
public class Main {
public static void main(String[] args) {
Animal a = new Dog(Xiao);
System.out.println(a.name); // 输出:Xiao
}
}
在这个代码中创建了一个叫 a 引用为Animal 的 Dog 对象
动态绑定
程序在
运行阶段才能确定使用那个方法
编译时只能确定方法签名,到运行时才能根据对象的实际类型决定调用哪个版本
类型:
- 除了静态绑定之外的,就是动态绑定
- 成员函数默认就是动态绑定.这也表现出 java 的多样性,是多态的bedrock
1 | class Animal { |
像程序一样思考: > 编译时: > 要调用a.eat(); 方法,
我进看看 a 的引用类型看看这个方法到底存不存在 > a 的引用类型是 Animal
他确实有 eat 方法. ✅编译通过, 但不决定调用哪个版本
运行时: JVM 检查
a实际指向的是Dog对象,去Dog类里找eat(),找到了就执行Dog.eat()
这种”运行时根据真实类型查找方法”的机制,就是动态绑定也叫虚方法调用(Virtual Method Invocation)
总结:
静态绑定
- 在编译过程中就确认了具体用哪个方法
动态绑定
- 在运行过程中才确认用哪个方法



