//author zzmpublicclassStaticDispatch{staticabstractclassHuman {}
staticclassManextendsHuman {}
staticclassWomanextendsHuman {}
publicvoid sayHello(Human guy){
System.out.println("hello guy");
}
publicvoid sayHello(Man guy){
System.out.println("hello gentleman");
}
publicvoid sayHello(Woman guy){
System.out.println("hello lady");
}
publicstaticvoid main(String[] args){
Human man = new Man();
Human woman = new Woman();
StaticDispatch sr = new StaticDispatch();
sr.sayHello(man);
sr.sayHello(woman);
}
}
_____________________________________________________________
运行结果:
hello guy
hello guy
对于上面的代码,我们先定义两个重要的概念:
Human man = new Man();
我们把"Human"称为变量man的静态类型或外观类型,而"Man"则称为变量man的实际类型。
main()里面的两次sayHello()方法调用,使用哪个重载版本,完全取决于传入参数的数量和数据类型。但虚拟机(编译器)重载时是通过参数的静态类型而不是实际类型作为判断依据的。并且静态类型是编译期可知的,因此,在编译阶段,Javac编译器会根据参数静态类型决定使用哪个重载版本,所以选择了sayHello(Human)作为调用目标。
所有依赖静态类型来定位方法执行版本的分派动作称为静态分派,静态分派的典型应用是方法重载。
动态分派
动态分派与重写(Override)有着很密切的关联,我们依旧用一段代码来演示动态分派。
//author zzmpublicclassDynamicDispatch {staticabstractclassHuman{protectedabstractvoid sayHello();
}
staticclassManextendsHuman {
@Override
protectedvoid sayHello(){
System.out.println("man say hello");
}
}
staticclassWomanextendsHuman {
@Override
protectedvoid sayHello(){
System.out.println("woman say hello");
}
}
publicstaticvoid main(String[] args){
Human man = new Man();
Human woman = new Woman();
man.sayHello();
woman.sayHello();
man = new Woman();
man.sayHello();
}
}
_______________________________________________________________
运行结果:
man say hello
woman say hello
woman say hello