Java中的动态方法调度

时间:2010-09-20 14:30:06

标签: java polymorphism

以下是关于我怀疑的代码信息。

class A {
    void someMethod(A param) {
        System.out.println("A");
    }
}

class C extends A {
    void someMethod(C param) {
        System.out.println("C");
    }
}

class DMD {
    public static void main(String[] args) {
        A ac = new C();
        C c = new C();
        ac.someMethod(c);
    }
}

输出:

A

但我将输出排除为

C

因为我为C分配了内存,而A指的是C的内存位置,所以如果我在A引用上调用该方法,那么指向C,并且参数作为C类型传递,然后我希望someMethod(C)方法应该执行。

任何人都可以告诉我这种行为的正当理由吗?

提前致谢。

3 个答案:

答案 0 :(得分:3)

在编译时实现对采用不同参数类型(重载)的方法的方法调用。 (这是你的情况)

如果所有3个方法都接受了类型A的参数 - 即方法覆盖,那么只有多态才会发挥作用并且会触发C的方法,前提是存在继承关系在A和C之间,即C延伸A。

答案 1 :(得分:2)

决定使用哪种方法基本上有两个阶段:首先是重载决策,然后是方法调度。重载解析在编译时发生,在运行时调度方法。

在此示例中,重载决策决定应使用重载someMethod(A param),因为这是类someMethod中定义的A的唯一重载(以及{{1}的静态类型}是ac)。

在运行时决定使用A的哪个实现,但由于只有一个实现(someMethod(A param)不覆盖C.someMethod(C),因为someMethod(A)更具体C),A被选中。

答案 2 :(得分:0)

您编写的代码无法成功编译。你不能说“A ac = new C();”因为C不会扩展A.如果你声称已经运行了这个并获得了输出,那么你必须将正在运行的代码中的某些内容错误地复制到这篇文章中。

如果为了争论,你的代码确实说“A ac = new A();”,那么你的代码仍然无法运行,因为A.someMethod需要A,而不是一个C。语句ac.someMethod(c)执行函数A.someMethodac的类型为A,因此针对ac执行任何功能都会从类A获取该名称的功能。尝试将类型C的参数传递给声明为采用类型A的参数的函数不会“切换”您使用来自不同类的函数来获取此类参数。重载仅适用于类。

或许您正在考虑的是一个更像这样的例子:

class A {
    public void someMethod(A a) {
        System.out.println("A");
    }

    public void someMethod(B b) {
        System.out.println("B");
    }
}

class Dmd {
    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        a.someMethod(b);
    }
}

这将输出“B”。

这里的不同之处在于,类A有两个版本的函数someMethod。其中一个需要A,其中一个需要B。当我们使用B调用它时,我们会获得B版本。

您是否看到这与您的示例有何不同?您正在声明三个类,每个类都带有一个函数someMethod。这里我们有一个类,它有两个名为someMethod的函数。这在Java中是非常不同的。