解释一个概念,宗量:方法的调用者和参数统称为方法的宗量。
前面讲了Java的分派调用,这里有一个更直观的例子来说明分派的过程,请看代码:
public class Dispatch {
static class QQ{}
static class _360{}
public static class Father{
public void hardChoice(QQ arg)
{
System.out.println("father choose qq");
}
public void hardChoice(_360 arg)
{
System.out.println("father choose 360");
}
}
public static class Son extends Father{
public void hardChoice(QQ arg)
{
System.out.println("son choose qq");
}
public void hardChoice(_360 arg)
{
System.out.println("son choose 360");
}
}
public static void main(String[] args) {
Father father = new Father();
Father son = new Son();
father.hardChoice(new _360());
son.hardChoice(new QQ());
}
}
运行结果:
father choose 360
son choose qq
为什么会出现这样的结果呢?
虚方法的执行分为了下面两个阶段:
1.静态分派:这时候选择目标方法的依据有两点
(1)静态类型是Father还是Son
(2)方法参数是QQ还是360
这次选择结果的最终产物是产生了两条invokevirtual指令,两条指令的参数分别为常量池中指向Father.hardChoice(_360)以及Father.hardChoice(QQ)的符号引用,因为是根据两个宗量进行选择,所以Java语言的静态分派属于多分派类型。
2.动态分派:
在执行Father.hardChoice(_360)以及Father.hardChoice(QQ)时,虚拟机此时不会关心传递过来的"QQ"到底是"腾讯QQ"还是"奇瑞QQ",因为这时候参数的静态类型和实际类型都不会对方法的选择构成任何影响,唯一可以影响虚拟机选择的因素只有此方法的调用者的实际类型是Father还是Son。
因为只有一个宗量作为选择依据,所以Java的动态分派属于单分派类型。
这个例子也说明了重载和重写的原理。
综上所述:Java语言是一门静态多分派,动态单分派的语言。