单分派,多分派

方法的接收者和方法的参数统称为方法的宗量。 根据分派基于宗量多少(接收者是一个宗量,参数是一个宗量),可以将分派分为单分派和多分派。单分派是指根据一个宗量就可以知道调用目标(即应该调用哪个方法),多分派需要根据多个宗量才能确定调用目标。

如下代码:

package diptch;

public class DynamicDispatch {

    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 {
        @Override
        public void hardChoice(QQ arg) {
            System.out.println("son choose QQ");
        }

        @Override
        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

来看字节码字节码指令具体执行:

  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=3, args_size=1
         0: new           #16                 // class diptch/DynamicDispatch$Fa
ther
         3: dup
         4: invokespecial #18                 // Method diptch/DynamicDispatch$F
ather."<init>":()V
         7: astore_1
         8: new           #19                 // class diptch/DynamicDispatch$So
n
        11: dup
        12: invokespecial #21                 // Method diptch/DynamicDispatch$S
on."<init>":()V
        15: astore_2
        16: aload_1
        17: new           #22                 // class diptch/DynamicDispatch$_3
60
        20: dup
        21: invokespecial #24                 // Method diptch/DynamicDispatch$_
360."<init>":()V
        24: invokevirtual #25                 // Method diptch/DynamicDispatch$F
ather.hardChoice:(Ldiptch/DynamicDispatch$_360;)V
        27: aload_2
        28: new           #29                 // class diptch/DynamicDispatch$QQ

        31: dup
        32: invokespecial #31                 // Method diptch/DynamicDispatch$Q
Q."<init>":()V
        35: invokevirtual #32                 // Method diptch/DynamicDispatch$F
ather.hardChoice:(Ldiptch/DynamicDispatch$QQ;)V
        38: return
      LineNumberTable:
        line 31: 0
        line 32: 8
        line 33: 16
        line 34: 27
        line 35: 38
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      39     0  args   [Ljava/lang/String;
               8      31     1 father   Ldiptch/DynamicDispatch$Father;
              16      23     2   son   Ldiptch/DynamicDispatch$Father;
}

C:\Users\Administrator\js>

首先确定方法的接收者,发现两个对象变量的静态类型都是Father类型的,因此在class文件中写的Father类中方法的符号引用如下。

24: invokevirtual #25  //Methoddiptch/DynamicDispatch$Father.hardChoice(Ldiptch/DynamicDpatch$_360;)V


35: invokevirtual #32                 // Method diptch/DynamicDispatch$F
ather.hardChoice:(Ldiptch/DynamicDispatch$QQ;)V            

两个方法的接受者都是Father 这个静态类型,形参部分的具体类型也是在编译器就已经确定了静态类型,然后各自找各自的方法所以静态类型属于多分派

然后在看son.hardChoice(new QQ());这个方法 son的静态类型是Father,实际类型是Son,准确的说是在执行invokevirtual 这个字节码指令时,他只会关心你的实际类型,而不会去操心你的参数,因为这时候方法形参不管是实际类型,还是静态类型都不会对方法的选择有任何影响。

猜你喜欢

转载自blog.csdn.net/qq_36866808/article/details/79027563
今日推荐