开课吧Java课堂之动态方法调度

111 阅读2分钟

前几篇文章的例题说明了方法重载机制,但并没有显示它们的作用。实际上,如果方法重载只是一个名字空间的约定,那么它最多是有趣的,但是没有实际价值的。

然而,情况并不如此。方法重载构成Java的一个最强大的概念的基础:动态方法调度。动态方法调度是一种在运行时而不是编译时调用重载方法的机制。动态方法调度是很重要的,因为这也是Java实现运行时多态性的基础。

让我们从重述一个重要的原则开始:超类的引用变量可以引用子类对象。Java用这一事实来解决在运行期间对重载方法的调用。过程如下:当一个重载方法通过超类引用被调用,Java根据当前被引用对象的类型来决定执行哪个版本的方法。

如果引用的对象类型不同,就会调用一个重载方法的不同版本。换句话说,是被引用对象的类型(而不是引用变量的类型)决定执行哪个版本的重载方法。因此,如果超类包含一个被子类重载的方法,那么当通过超类引用变量引用不同对象类型时,就会执行该方法的不同版本。

下面是阐述动态方法调度的例子:

// Dynamic Method Dispatch 
class A { 
 void callme() { 
 System.out.println("Inside A's callme method"); 
 } 
} 
class B extends A { 
 // override callme() 
 void callme() { 
 System.out.println("Inside B's callme method"); 
 } 
} 
class C extends A { 
 // override callme() 
 void callme() { 
 System.out.println("Inside C's callme method"); 
 } 
} 
class Dispatch { 
 public static void main(String args[]) { 
 A a = new A(); // object of type A 
 B b = new B(); // object of type B 
 C c = new C(); // object of type C 
 A r; // obtain a reference of type A 
 r = a; // r refers to an A object 
 r.callme(); // calls A's version of callme 
 r = b; // r refers to a B object 
 r.callme(); // calls B's version of callme 
 r = c; // r refers to a C object 
 r.callme(); // calls C's version of callme 
 } 
}

该程序的输出如下:

Inside A’s callme method 
Inside B’s callme method 
Inside C’s callme method

程序创建了一个名为A的超类以及它的两个子类B和C。子类B和C重载A中定义的callme( )方法。main( )主函数中,声明了A、B和C类的对象。而且,一个A类型的引用r也被声明。

就像输出所显示的,所执行的callme( )版本由调用时引用对象的类型决定。如果它是由引用变量r的类型决定的,你将会看到对A的callme( )方法的三次调用。

熟悉C++的读者会认同Java中的重载方法与C++中的虚函数类似。