Java方法重载+双重调度

Max*_*Max 16 java oop overloading double-dispatch

任何人都可以详细解释在我的测试代码中print(Parent parent)使用Child实例时调用重载方法的原因吗?

这里涉及到Java中的任何虚拟方法或方法的重载/解决方案?有没有直接引用Java Lang Spec?哪个术语描述了这种行为?非常感谢.

public class InheritancePlay {

    public static class Parent {        
        public void doJob(Worker worker) {
            System.out.println("this is " + this.getClass().getName());

            worker.print(this);
        }
    }

    public static class Child extends Parent {
    }

    public static class Worker {
        public void print(Parent parent) {
            System.out.println("Why this method resolution happens?");
        }

        public void print(Child child) {
            System.out.println("This is not called");
        }
    }

    public static void main(String[] args) {
        Child child = new Child();
        Worker worker = new Worker();

        child.doJob(worker);
    }
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*rau 23

JLS在§8.4.9声明重载:

  1. 调用方法时(第15.12节),在编译时使用实际参数的数量(以及任何显式类型参数)和参数的编译时类型来确定将被调用的方法的签名( §15.12.2).
  2. 如果要调用的方法是实例方法,则将在运行时使用动态方法查找(第15.12.4节)确定要调用的实际方法.

所以在你的情况下:

  1. 方法argument(this)是编译时类型Parent,因此print(Parent)调用该方法.
  2. 如果Worker该类是子类,并且子类将覆盖该方法,并且该worker实例属于该子类,则将调用重写的方法.

Java中不存在双重调度.您必须模拟它,例如使用访客模式.在这种模式中,基本上,每个子类实现一个accept方法并使用thisas参数调用visitor ,并且this具有子类的编译时类型,因此使用了所需的方法重载.


rsp*_*rsp 5

原因是它doJob实现了Parent而不是重载Child.它传递this给worker的print方法,因为this它是调用Parent方法的类型Worker::print(Parent).

为了有Worker::print(Parent)叫你needto超载doJobChild:

public static class Child extends Parent {
    public void doJob(Worker worker) {
        System.out.println("from Child: this is " + this.getClass().getName());

        worker.print(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码this.getClass()Child相当于Child.class.