目录
1. 基本介绍
(1)多态指方法或对象具有多种形态。
(2)多态的前提:建立在封装和继承的基础上,两个对象(类)存在继承关系。
2. 具体体现
(1)方法的多态
重写和重载就体现多态。
(2)对象的多态(核心)
①一个对象的编译类型和运行类型可以不一致。
例:Animal 是Dog的父类,执行Animal animal = new Dog(); 时,对象animal的编译类型是Animal,运行类型是Dog。(程序在运行时,方法和属性的调用,看的是运行类型)
②对象的编译类型,在定义对象时,就已经被确定了,不能再改变。
③对象的运行类型,是可以变化的。
例:接着上个例子,在执行animal = new Cat(); 后,animal的运行类型变成了Cat,但编译类型还是Animal
④编译类型看定义时“=”号的左边,运行类型看“=”号的右边。
3. 注意事项和使用细节
(1)向上转型
①本质:父类的引用指向了子类的对象
②语法:父类类型 引用名 = new 子类类型();
例如 前面的Animal animal = new Dog();
③特点:编译类型看左边,运行类型看右边。可以调用父类中所有的成员(需要遵循访问权限),不能调用子类中特有的成员(因为在编译阶段,能调用哪些成员,是由编译类型来决定的),最终的运行效果要看子类的具体实现(因为运行程序后,调用方法时,是由运行类型决定的,将从子类开始查找方法)。
(2)向下转型
①语法:子类类型 引用名 = (子类类型) 父类引用;
例:Dog dog = (Dog) animal; (编译类型:Dog 运行类型:Dog)
②只能强转父类的引用,不能强转父类的对象。
③要求 父类的引用 必须指向的是 当前目标类型的对象。
例如:之前animal向上转型的类是Dog,此时向下转型dog的类也只能是Dog,而不能是其它类。
④当向下转型后,可以调用子类中的所有成员(属性和方法)。
(3)属性不能重写,属性的值看编译类型。
(4)instanceof 类型比较操作符
用于判断 对象的运行类型 是否为 比较的这个类型 或 这个类型的子类型。
(5)java的动态绑定机制(重点)
①当调用对象的方法时,该方法会和该对象的运行类型/内存地址绑定。(当调用方法时,从当前类查找跳转到了其它类去,在进行方法调用的判断时,也是直接找到该对象的运行类型)
②当调用对象的属性时,没有动态绑定机制,哪里声明,就在那里调用。(跳转到其它类去后,就在当前类进行属性调用)
4. 多态的应用
(1)多态数组
①数组的定义类型为 父类类型,里面保存的实际元素类型为 该类类型或 该类的子类类型。
例:Student和Teacher是Person的子类
②如果子类中定义了特有的方法,不能直接调用(因为编译类型为父类,父类中没有子类特有的方法),则需要使用 类型判断 + 向下转型 来调用。
(2)多态参数
①方法定义的形参类型为 父类类型,实参类型允许为 该类型 或 该类型的子类类型。
例:Student是Person的子类