1. 什么是多态
同类型的对象,表现出的多种形态
2. 多态的表现形式
父类类型 对象名称 = 子类对象;
3. 多态的前提
- 有继承/实现关系
- 有父类引用指向子类对象
Fu f = new Zi (); - 有方法重写
4. 多态的好处
- 使用父类作为参数,可以接收所有子类对象
- 使用父类作为参数,和方法的调用者,可以根据传递对象的不同,调用不同对象的重写后的方法。
- 体现多态的扩展性和便利
5. 多态中调用成员的特点
- 变量调用:编译看左边,运行也看左边
a. 编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有,编译失败
b. 运行也看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值 - 方法调用:编译看左边,运行看右边
a. 编译看左边:javac编译代码的时候,会看左边的父类中有没有这个方法,如果有,编译成功,如果没有,编译失败。
b. 运行看右边:java运行代码的时候,实际上运行的是子类中,已经重写过的方法。 - 如何理解:
编译时:
Animal a = new Dog();
sout(a.name);
a.show();
现在是用a去调用变量和方法,而a是Animal类型的,所以不管是调用变量还是方法,默认都会从Animal这个类中去找,但先不会调用。
运行时:
成员变量:在子类的对象中,会把父类的成员变量也继承下来的。
父(Animal):name 子(Dog):name
对于Dog d = new Dog();
sout(d.name);
如果用Dog类型的d变量来调用name,他就会调用子类里的name
成员方法:如果子类对方法进行了重写,那么在虚方法表中是会把父类的方法进行覆盖的。
对于Animal a = new Dog();
a.show();
如果用Animal类型的a变量来调用show()方法,他是调用子类里的方法。
对于Dog d = new Dog();
d.show();
如果用Dog类型的d变量来调用show()方法,他也是会调用子类里的方法。
- 多态调用成员的内存图
- java中,加载字节码文件的顺序,永远是先加载父类,然后再加载子类
- 如果是用多态调用变量(即Animal a = new Dog();),会直接在堆内存中的对象当中看,从父类里面继承下来的变量里,有没有name,如果有,则编译成功,如果没有则编译失败,报错
- 如果是用多态调用方法,会先去方法区中找父类的字节码文件中有没有show()方法,如果没有,则编译失败,报错。如果找到了,则继续去方法区中找子类的字节码文件中的show()方法,若找到了就调用这个子类的方法,若没找到,则调用父类的这个方法。
- 如果没有用多态调用变量或方法(即Dog d = new Dog();),则按正常继承中访问成员变量或成员方法的规则去找