这篇文章主要介绍了 java 多态性详解及常见面试题的相关资料, 这里对 java 的多态性做了资料整理, 并列举常见的关于多态性的面试题, 需要的朋友可以参考下
java 多态性
多态分两种:
(1) 编译时多态(设计时多态): 方法重载
(2) 运行时多态: JAVA 运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为运行时多态(我们平时说得多的事运行时多态, 所以多态主要也是指运行时多态)
运行时多态存在的三个必要条件:
一要有继承(包括接口的实现);
二要有重写;
三父类引用指向子类对象
多态的好处:
1. 可替换性 (substitutability) 多态对已存在代码具有可替换性例如, 多态对圆 Circle 类工作, 对其他任何圆形几何体, 如圆环, 也同样工作
2. 可扩充性 (extensibility) 多态对代码具有可扩充性增加新的子类不影响已存在类的多态性继承性, 以及其他特性的运行和操作实际上新加子类更容易获得多态功能例如, 在实现了圆锥半圆锥以及半球体的多态基础上, 很容易增添球体类的多态性
3. 接口性 (interface-ability) 多态是超类通过方法签名, 向子类提供了一个共同接口, 由子类来完善或者覆盖它而实现的如图 8.3 所示图中超类 Shape 规定了两个实现多态的接口方法, computeArea()以及 computeVolume()子类, 如 Circle 和 Sphere 为了实现多态, 完善或者覆盖这两个接口方法
4. 灵活性 (flexibility) 它在应用中体现了灵活多样的操作, 提高了使用效率
5. 简化性 (simplicity) 多态简化对应用软件的代码编写和修改过程, 尤其在处理大量对象的运算和操作时, 这个特点尤为突出和重要
注意: 优先级从高到低: this.show(O)super.show(O)this.show((super)O)super.show((super)O)
相关面试题:
- class A {
- public String show(D obj)...{
- return ("A and D");
- }
- public String show(A obj)...{
- return ("A and A");
- }
- }
- class B extends A{
- public String show(B obj)...{
- return ("B and B");
- }
- public String show(A obj)...{
- return ("B and A");
- }
- }
- class C extends B...{}
- class D extends 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));
- System.out.println(a1.show(c));
- System.out.println(a1.show(d));
- System.out.println(a2.show(b));
- System.out.println(a2.show(c));
- System.out.println(a2.show(d));
- System.out.println(b.show(b));
- System.out.println(b.show(c));
- System.out.println(b.show(d));
(三)答案
- 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
分析:
做这种题的话要时时刻刻使用那个优先级顺序:
对于第一题:
a1 是 A 类的一个实例化对象, 所以 this 指向 A, 然后查找 this.show(b), 由于没有这个方法, 所以到 super.show(b), 但是由于 A 类没有超类了, 所以到 this.show(super b), 由于 b 的超类是 A, 所以相当于 this.show(A), 然后在 A 类中查找到了这个方法, 于是输出 A and A
对于第二题:
同样, a1 是 A 类的实例化对象, 所以 this 指向 A, 然后在 A 类中查找 this.show(C)方法, 由于没有这个方法, 所以到了 super.show(C), 由于 A 类的超类里面找, 但是 A 没有超类, 所以到了 this.show(super C), 由于 C 的超类是 B 所以在 A 类里面查找 this.show(B)方法, 也没找到, 然后 B 也有超类, 就是 A, 所以查找 this.show(A), 找到了, 于是输出 A and A;
对于第三题:
同样, a1 是 A 类的实例化对象, 所以 this 指向 A, 然后在 A 类中找到 this.show(D)方法, 找到了, 所以就输出 A and D;
对于第四题:
a2 是 B 类的引用对象, 类型为 A, 所以 this 指向 A 类, 然后在 A 类里面找 this.show(B)方法, 没有找到, 所以到了 super.show(B), 由于 A 类没有超类, 所以到了 this.show(super B),B 的超类是 A, 即 super B = A, 所以执行方法 thisshow(A), 在 A 方法里面找 show(A), 找到了, 但是由于 a2 是一个类 B 的引用对象, 而 B 类里面覆盖了 A 类的 show(A)方法, 所以最终执行的是 B 类里面的 show(A)方法, 即输出 B and A;
对于第五题:
a2 是 B 类的引用对象, 类型为 A, 所以 this 指向 A 类, 然后在 A 类里面找 this.show(C)方法, 没有找到, 所以到了 super.show(C)方法, 由于 A 类没有超类, 所以到了 this.show(super C),C 的超类是 B, 所以在 A 类里面找 show(B), 同样没有找到, 发现 B 还有超类, 即 A, 所以还继续在 A 类里面找 show(A)方法, 找到了, 但是由于 a2 是一个类 B 的引用对象, 而 B 类里面覆盖了 A 类的 show(A)方法, 所以最终执行的是 B 类里面的 show(A)方法, 即输出 B and A;
对于第六题:
a2 是 B 类的引用对象, 类型为 A, 所以 this 指向 A 类, 然后在 A 类里面找 this.show(D)方法, 找到了, 但是由于 a2 是一个类 B 的引用对象, 所以在 B 类里面查找有没有覆盖 show(D)方法, 没有, 所以执行的是 A 类里面的 show(D)方法, 即输出 A and D;
对于第七题:
b 是 B 类的一个实例化对象, 首相执行 this.show(B), 在 B 类里面找 show(B)方法, 找到了, 直接输出 B and B;
对于第八题:
b 是 B 类的一个实例化对象, 首相执行 this.show(C), 在 B 类里面找 show(C)方法, 没有找到, 所以到了 super.show(c),B 的超类是 A, 所以在 A 类中找 show(C)方法, 没有找到, 于是到了 this.show(super C),C 的超类是 B, 所以在 B 类中找 show(B)f 方法, 找到了, 所以执行 B 类中的 show(B)方法输出 B and B;
对于第九题:
b 是 B 类的一个实例化对象, 首相执行 this.show(D), 在 B 类里面找 show(D)方法, 没有找到, 于是到了 super.show(D),B 的超类是 A 类, 所以在 A 类里面找 show(D)方法, 找到了, 输出 A and D;
这是我看过网上的题目之后总结出来的方法, 希望对大家有好处
来源: http://www.phperz.com/article/18/0221/359405.html