多态性的理解:

可以理解为一个事物的多种形态。

何为多态性:

在Java中的体现为对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)。

  • 可以直接应用在抽象类和接口上

举例:
Person p = new Man();———Man是Person的子类;
作用:
提高了代码的通用性,常称作接口重用
注意:

  • 多态性的使用前提:① 需要存在继承或者实现关系 ② 方法的重写
  • 对象的多态性,只适用于方法,不适用于属性(属性:编译和运行都看左边)
  • 在多态中,父类对象不能调用子类特有的方法和属性;只能调用父类中声明的方法(未重写时)或子类重写父类的方法;
  • 有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。如何才能调用子类特的属性和方法?应使用向下转型。

虚拟方法调用(Virtual Method Invocation):

  • 子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。

Java引用变量有两个类型:

  • 编译时类型和运行时类型
    1. 编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简称:编译时,看左边;运行时,看右边。
    2. 若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism) (我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。)
    • 多态情况下

“看左边” :看的是父类的引用(父类中不具备子类特有的方法)
“看右边” :看的是子类的对象(实际运行的是子类重写父类的方法)

向上转型与向下转型:

image.png

  • 向上转型(upcasting):子类可看做是特殊的父类,所以父类类型的引用可以指向子类的对象。(即多态)
  • 向下转型:使用强制类型转换符:()

注:

  • 从子类到父类的类型转换可以自动进行
  • 从父类到子类的类型转换必须通过造型(强制类型转换)实现
  • 无继承关系的引用类型间的转换是非法的
  • 使用强转时,可能出现ClassCastException的异常。在造型前可以使用instanceof操作符测试一个对象的类型

instanceof 操作符

x instanceof A:检验x是否为类A的对象,返回值为boolean型。

  • 要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
  • 如果x属于类A的子类B(即:A是x的间接父类),x instanceof A值也为true。

多态笔试题:

  1. public static void main(String[] args) {
  2. Base base = new Sub();
  3. // 多态:调用子类重写方法
  4. base.add(1, 2, 3);// sub1
  5. Sub s = (Sub) base;
  6. s.add(1, 2, 3);// sub2
  7. }
  8. class Base {
  9. public void add(int a, int... arr) {
  10. System.out.println("base");
  11. }
  12. }
  13. class Sub extends Base {
  14. // 与父类base中的add方法构成重写
  15. public void add(int a, int[] arr) {
  16. System.out.println("sub_1");
  17. }
  18. // 与add(int a, int[] arr)构成重载,且优先调用此方法
  19. // 与父类base中的add方法构成重载
  20. public void add(int a, int b, int c) {
  21. System.out.println("sub_2");
  22. }
  23. }