标签:一个 练习 tail 定义 xtend main return stat 对象引用
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
public class Dtailianxi { public static void main(String[] args){ A a=new B(); A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); /* System.out.println(a1.show(b)); //1 A and A B是A的子类 System.out.println(a1.show(c)); //2 A and A System.out.println(a1.show(d)); //3 A and D System.out.println(a2.show(b)); //4 A and A//A类没有show(B b)方法,所以只能从父类找可以包含b类的方法 System.out.println(a2.show(c)); //5 A and A//A类没有show(B b)方法,所以只能从父类找可以包含b类的方法 System.out.println(a2.show(d)); //6 A and D System.out.println(b.show(b)); //7 B and B System.out.println(b.show(c)); //8 B and B System.out.println(b.show(d)); //9 A and D
class A { public String show( A obj) { return ("A and A"); } public String show( D obj) { return ("A and D"); } } class B extends A { public String show( B obj) { return ("B and B"); } } class C extends B{} class D extends B{}
刚看到这个小练习的时候,看到System.out.println(a1.show(b));这第一个输出语句就蒙了,看下边的解释也看不明白,这个a1.show(b)就是调用了a1的一个方法,而b为a的一个继承类,所以可以把b看做是a,那么输出的语句就是A and A了,下边这个同理,第三个,以为在类A 中已经定义了对象D的一个方法,所以会去调用这个方法。第四个输出语句刚开始我也以为应该是B and B,看创建对象是A类的引用指向了B,因为B.show(B b)是B类自己定义的一个方法,所以a是调用不到的,只能从A类中找,所以输出结果为A and A,第五个a2.show(c)也是这样,下面的几个也是这样。
引用其他博客的解释:
按照上面的方法,可以正确得到其他的结果。
问题还要继续,现在我们再来看上面的分析过程是怎么体现出蓝色字体那句话的内涵的。它说:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。还是拿a2.show(b)来说吧。
a2是一个引用变量,类型为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)。这就是那句话的意义所在,到这里,我们可以清晰的理解Java的多态性了。
标签:一个 练习 tail 定义 xtend main return stat 对象引用
原文地址:http://www.cnblogs.com/gaofangquan/p/7231281.html