多态分两种:

(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)。

相关面试题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 {}

(二)问题:以下输出结果是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main() {
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)); // ⑨
}

(三)答案

1
2
3
4
5
6
7
8
9
①   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

分析:

做这种题的话要时时刻刻使用那个优先级顺序:注意:优先级从高到低:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

  1. 对于第一题:

a1A类的一个实例化对象,所以this指向A,然后查找this.show(b),由于没有这个方法,所以到super.show(b),但是由于A类没有超类了,所以到this.show(super b),由于b的超类是A,所以相当于this.show(A),然后在A类中查找到了这个方法,于是输出A and A

  1. 对于第二题:

同样,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

  1. 对于第三题:

同样,a1A类的实例化对象,所以this指向A,然后在A类中找到this.show(D)方法,找到了,所以就输出A and D

  1. 对于第四题:

a2B类的引用对象,类型为A,所以this指向A类,然后在A类里面找this.show(B)方法,没有找到,所以到了super.show(B),由于A类没有超类,所以到了this.show(super B)B的超类是A,即super B = A,所以执行方法this.show(A),在A方法里面找show(A),找到了,但是由于a2是一个类B的引用对象,而B类里面覆盖了A类的show(A)方法,所以最终执行的是B类里面的show(A)方法,即输出B and A

  1. 对于第五题:

a2B类的引用对象,类型为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

  1. 对于第六题:

a2B类的引用对象,类型为A,所以this指向A类,然后在A类里面找this.show(D)方法,找到了,但是由于a2是一个类B的引用对象,所以在B类里面查找有没有覆盖show(D)方法,没有,所以执行的是A类里面的show(D)方法,即输出A and D

  1. 对于第七题:

bB类的一个实例化对象,首相执行this.show(B),在B类里面找show(B)方法,找到了,直接输出B and B

  1. 对于第八题:

bB类的一个实例化对象,首相执行this.show(C),在B类里面找show(C)方法,没有找到,所以到了super.show(c)B的超类是A,所以在A类中找show(C)方法,没有找到,于是到了this.show(super C)C的超类是B,所以在B类中找show(B)方法,找到了,所以执行B类中的show(B)方法输出B and B

  1. 对于第九题:

bB类的一个实例化对象,首相执行this.show(D),在B类里面找show(D)方法,没有找到,于是到了super.show(D)B的超类是A类,所以在A类里面找show(D)方法,找到了,输出A and D

写在最后

欢迎大家关注鄙人的公众号【麦田里的守望者zhg】,让我们一起成长,谢谢。
微信公众号