打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
深入理解Java多态性
  1. class A
  2. {
  3. public String show(D obj)
  4. {
  5. return ("A and D");
  6. }
  7. public String show(A obj)
  8. {
  9. return ("A and A");
  10. }
  11. }
  12. class B extends A
  13. {
  14. public String show(B obj)
  15. {
  16. return ("B and B");
  17. }
  18. public String show(A obj)
  19. {
  20. return ("B and A");
  21. }
  22. }
  23. class C extends B
  24. {
  25. }
  26. class D extends B
  27. {
  28. }
  29. public class Foo
  30. {
  31. public static void main(String[] args)
  32. {
  33. A a1 = new A();
  34. A a2 = new B();
  35. B b = new B();
  36. C c = new C();
  37. D d = new D();
  38. System.out.println(a1.show(b)); // (1)
  39. System.out.println(a1.show(c)); // (2)
  40. System.out.println(a1.show(d)); // (3)
  41. System.out.println(a2.show(b)); // (4)
  42. System.out.println(a2.show(c)); // (5)
  43. System.out.println(a2.show(d)); // (6)
  44. System.out.println(b.show(b)); // (7)
  45. System.out.println(b.show(c)); // (8)
  46. System.out.println(b.show(d)); // (9)
  47. }
  48. }

打印:

  1. A and A // (1)
  2. A and A // (2)
  3. A and D // (3)
  4. B and A // (4)
  5. B and A // (5)
  6. A and D // (6)
  7. B and B // (7)
  8. B and B // (8)
  9. A and D // (9)

分析:

当超类对象引用变量引用子类对象时, 被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法, 但是这个被调用的方法必须是在超类中定义过的, 也就是说被子类覆盖的方法. (但是如果强制把超类转换成子类的话, 就可以调用子类中新添加而超类没有的方法了.)

这里涉及方法调用的优先级问题, 优先级由高到低依次为: this.show(O), super.show(O), this.show((super)O), super.show((super)O).

比如(4), a2. show(b), a2是一个引用变量, 类型为A, 则this为a2, b是B的一个实例, 于是它到类A里面找show(B obj)方法, 没有找到, 于是到A的super(超类)找, 而A没有超类, 因此转到第三优先级this. show((super)O), this仍然是a2, 这里O为B, (super)O即(super)B即A, 因此它到类A里面找show(A obj)的方法, 类A有这个方法, 但是由于a2引用的是类B的一个对象, B覆盖了A的show(A obj)方法, 因此最终锁定到类B的show(A obj), 输出为"B and A".

再比如(8), b. show(c), b是一个引用变量, 类型为B, 则this为b, c是C的一个实例, 于是它到类B找show(C obj)方法, 没有找到, 转而到B的超类A里面找, A里面也没有, 因此也转到第三优先级this. show((super)O), this为b, O为C, (super)O即(super)C即B, 因此它到B里面找show(B obj)方法, 找到了, 由于b引用的是类B的一个对象, 因此直接锁定到类B的show(B obj), 输出为"B and B".

按照上面的方法, 可以正确得到其他的结果.

问题还要继续, 现在我们再来看上面的分析过程是怎么体现出蓝色字体那句话的内涵的. 它说: 当超类对象引用变量引用子类对象时, 被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法, 但是这个被调用的方法必须是在超类中定义过的, 也就是说被子类覆盖的方法. 还是拿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). 这就是那句话的意义所在.

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
面向对象之多态【向上转型与向下转型】
深入理解java多态性
java超类
Java学习——36、类的多态(一)
Java 面向对象知识点整理
Java继承详解
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服