多态
1、多态:事物的多种状态,polymorphic
对象的多态性:同一个对象,可能具有不同的名称,同一个对象,有不同的类型的引用指向它。
本质:同一个物体有不同的名称和描述。 狗 :狗 动物
类型的多态性:同一个类型,可能具有不同的子类实现,同一个类型引用,有不同的对象实现,
本质:同一个名字和描述,可以在不同场景下有不同的真实实现。
动物: 狗 猫 猪
2、多态的前提
子类继承父类 方法的重写 父类的引用指向子类的对象
class Test { public static void main(String[] args) { Person p = new P1();//父类的引用指向子类的对象 p.run(); } } class Person { public void run(){ System.out.println("走走走"); } } class P1 extends Person //继承 { public void run(){//方法的重写 System.out.println("跑起来"); } }
3、多态中成员变量的访问特点
编译看左边,运行看左边(编译时看父类是否有该变量的定义,运行时获取到的是父类的结果)
在子类对象中有一块区域是super区域,存放继承父类的变量和方法,容易理解,变量a的类型是Fu类型,
因此a.age可以看做是supper.age,所以输出就是Fu.age变量。
4、多态中成员方法的访问特点
编译看左边,运行看右边(编译时看父类是否定义该方法,运行时运行子类重写的方法)
动态绑定
在JVM执行到方法时,会根据这个方法所属变量类型标识符找到该方法的全限定名(包名+类名),
这里所属变量类型是父类,但是只知道所属变量类型还不能够的,因为无法确定方法的具体位置(非静态
方法肯定是在堆中),就无法压到栈中执行,因此必须根据父类变量创建的实际对象确定方法的具体位置
(在堆中寻找),这种在程序执行过程中,通过动态创建的方法表来定位方法的方式,称为动态绑定。
5、多态中静态方法的访问特点
编译看左边,运行看左边(编译时看父类是否定义该方法,运行时运行父类的方法)
原因:方法属于类,和父类的方法不属于重写关系
静态变量:存储在类的字节码中的变量,被所有对象所共享,不随着对象的变化而变化,
都有相同的值,所以称为静态变量
静态方法:只会根据引用所属的父类,来决定运行的内容,运行内容,不会随着子类的变化而变化,
都是引用所属的父类的方法实现,所以称为静态方法。
public class Test { public static void main(String[] args) { Fu f = new Zi(); System.out.println(f.age); f.run(); f.show(); } } class Fu{ int age=10; public void run() { System.out.println("run run run"); } public static void show() { System.out.println("show show show"); } } class Zi extends Fu{ int age=5; public void run() { System.out.println("go go go"); } public static void show() { System.out.println("show time"); } }
6、向上向下转型
当想要访问子类中的属性或子类特有的方法时,需要向下转型
这里有一个instanceof方法,可以进行一次判断
格式:子类类型 引用名称 = (子类类型)父类类型的引用;
eg: Zi z = (Zi)f;
本质:恢复子类原本的访问范围
7、多态的好处
1、提高了代码的可扩展性
2、在方法的参数列表中,可以定义父类类型的引用,将来调用的时候,所有的子类类型的对象,
都可以作为方法的实际参数。
3、不在方法的参数列表中,就在普通的方法体中,使用父类的类型指向子类的对象,
也能提高代码的可扩展性。对象的来源非常广泛,不仅仅是new出来的,(还可能是通过反射获取的,
通过文件读取的,还可能是网络传递的,在写代码的编译阶段,无法知道对象具体的子类类型的)
需要使用父类类型的引用,操作不知道的子类类型的对象。