(一)相关类
(二)问题以下输出结果是什么?
(三)答案
① A and A
② A and A
③ A and D
④ B and A
⑤ B and A
⑥ A and D
⑦ B and B
⑧ B and B
⑨ A and D
(四)分析
①②③比较好理解一般不会出错④⑤就有点糊涂了为什么输出的不是B and B呢?!!先来回顾一下多态性
运行时多态性是面向对象程序设计代码重用的一个最强大机制动态性的概念也可以被说成一个接口多个方法Java实现运行时多态性的基础是动态方法调度它是一种在运行时而不是在编译期调用重载方法的机制
方法的重写Overriding和重载Overloading是Java多态性的不同表现重写Overriding是父类与子类之间多态性的一种表现重载Overloading是一个类中多态性的一种表现如果在子类中定义某方法与其父类有相同的名称和参数我们说该方法被重写(Overriding)子类的对象使用这个方法时将调用子类中的定义对它而言父类中的定义如同被屏蔽了如果在一个类中定义了多个同名的方法它们或有不同的参数个数或有不同的参数类型则称为方法的重载(Overloading)Overloaded的方法是可以改变返回值的类型方法的重写Overriding和重载Overloading是Java多态性的不同表现重写Overriding是父类与子类之间多态性的一种表现重载Overloading是一个类中多态性的一种表现如果在子类中定义某方法与其父类有相同的名称和参数我们说该方法被重写 (Overriding)子类的对象使用这个方法时将调用子类中的定义对它而言父类中的定义如同被屏蔽了如果在一个类中定义了多个同名的方法它们或有不同的参数个数或有不同的参数类型则称为方法的重载(Overloading)Overloaded的方法是可以改变返回值的类型
当超类对象引用变量引用子类对象时被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法但是这个被调用的方法必须是在超类中定义过的也就是说被子类覆盖的方法 (但是如果强制把超类转换成子类的话就可以调用子类中新添加而超类没有的方法了)
好了先温习到这里言归正传!实际上这里涉及方法调用的优先问题 优先级由高到低依次为thisshow(O)supershow(O)thisshow((super)O)supershow((super)O)让我们来看看它是怎么工作的
比如④ashow(b)a是一个引用变量类型为A则this为ab是B的一个实例于是它到类A里面找show(B obj)方法没有找到于是到A的super(超类)找而A没有超类因此转到第三优先级thisshow((super)O)this仍然是a这里O为B(super)O即(super)B即A因此它到类A里面找show(A obj)的方法类A有这个方法但是由于a引用的是类B的一个对象B覆盖了A的show(A obj)方法因此最终锁定到类B的show(A obj)输出为B and A
再比如⑧bshow(c)b是一个引用变量类型为B则this为bc是C的一个实例于是它到类B找show(C obj)方法没有找到转而到B的超类A里面找A里面也没有因此也转到第三优先级thisshow((super)O)this为bO为C(super)O即(super)C即B因此它到B里面找show(B obj)方法找到了由于b引用的是类B的一个对象因此直接锁定到类B的show(B obj)输出为B and B
按照上面的方法可以正确得到其他的结果
问题还要继续现在我们再来看上面的分析过程是怎么体现出蓝色字体那句话的内涵的它说当超类对象引用变量引用子类对象时被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法但是这个被调用的方法必须是在超类中定义过的也就是说被子类覆盖的方法还是拿ashow(b)来说吧
a是一个引用变量类型为A它引用的是B的一个对象因此这句话的意思是由B来决定调用的是哪个方法因此应该调用B的show(B obj)从而输出B and B才对但是为什么跟前面的分析得到的结果不相符呢?!问题在于我们不要忽略了蓝色字体的后半部分那里特别指明这个被调用的方法必须是在超类中定义过的也就是被子类覆盖的方法B里面的show(B obj)在超类A中有定义吗?没有!那就更谈不上被覆盖了实际上这句话隐藏了一条信息它仍然是按照方法调用的优先级来确定的它在类A中找到了show(A obj)如果子类B没有覆盖show(A obj)方法那么它就调用A的show(A obj)(由于B继承A虽然没有覆盖这个方法但从超类A那里继承了这个方法从某种意义上说还是由B确定调用的方法只是方法是在A中实现而已)现在子类B覆盖了show(A obj)因此它最终锁定到B的show(A obj)这就是那句话的意义所在