方法的接受者与方法的参数统称为方法的宗量。根据分派基于多少宗量,可以将分派分为单分派与多份派。
《深入理解java虚拟机》一书中写到,java是静态多分派动态单分派的语言,我一直没有理解,我觉得静态分派是根据方法参数的类型和顺序来决定调用哪一个重载方法。
而动态分派就是在运行期根据方法调用者的实际类型来决定调用哪一个重写的方法。这不都是单分派么?我不知道有没有读者有或者曾经有过与我相似的困惑,今天做到的一个试题让我明白了自己的想法错在哪儿。
class Base
{
public void method()
{
System.out.println("Base");
}
}
class Son extends Base
{
public void method()
{
System.out.println("Son");
}
public void methodB()
{
System.out.println("SonB");
}
}
public class Test01
{
public static void main(String[] args)
{
Base base = new Son();
base.method();
base.methodB();
}
}
这段代码我本以为输出会是Son SonB。但实际情况确是编译无法通过。为什么?问题出在base.methodB()这一句,我们知道多态发生的条件是,继承+方法重写+父类引用指向子类对象。base.methodB()这句话是没有发生多态行为的,因为methodB()并不是一个继承于子类并重写的方法,它是一个只存在于Son类中的方法。如果要调用methodB(),必须将base强转成son才可以。
编译期静态多分派就是指在编译期根据方法的参数的静态类型以及参数顺序和方法调用者的静态类型来选择方法。在这段代码中,base.methodB(),首先base的静态类型是Base,方法中不含参数。那么在编译器就会在常量池中寻找Base.methodB()这个符号引用,但是找不到啊,因为Base类中根本就没有methodB()这个方法。所以就会出现编译不通过的现象。所以静态多分派。