1. Java解析
动态分派
源码:
public class DynamicDispatch {
public static class Human {
void sayHello() {
System.out.println("human say hello!");
}
}
static class Man extends Human {
@Override
void sayHello() {
System.out.println("man say hello!");
}
}
static class Woman extends Human {
@Override
void sayHello() {
System.out.println("human say hello!");
}
}
public static void main(String[] args) {
Human human = new Human();
Human man = new Man();
Human woman = new Woman();
human.sayHello();
man.sayHello();
woman.sayHello();
}
}
分析:
通过javap -v DynamicDispatch.class 获取编译后的二进制文件:
总结:
不是根据静态类型来确定,而是在运行时根据实际类型来决定函数的版本。
静态分派
源码:
public class StaticDispatch {
static class Human {
}
static class Man extends Human {
}
static class Woman extends Human {
}
void sayHello(Human human) {
System.out.println("human say hello!");
}
void sayHello(Man man) {
System.out.println("man say hello!");
}
void sayHello(Woman woman) {
System.out.println("woman say hello!");
}
public static void main(String[] args) {
StaticDispatch staticDispatch = new StaticDispatch();
Human human = new Human();
Human man = new Man();
Human woman = new Woman();
staticDispatch.sayHello(human);
staticDispatch.sayHello(man);
staticDispatch.sayHello(woman);
}
}
分析:
通过javap -v StaticDispatch.class 获取编译后的二进制文件:
通过这段编译,上述的三个方法都初始化了,但是最后再调用的都是human的sayHello方法。
总结:由于静态分派是在类编译的时候确定类的属性。
编译器在重载时是通过参数的静态类型而不是实际类型作为判定依据的。并且静态类型是编译期可知的,因此,在编译阶段,Javac编译器会根据参数的静态类型决定使用哪个重载版本。
Java语言是一门静态多分派、 动态单分派的语言。