多态性(Polymorphism)
理解多态性:可以理解为一个事物的多种形态;
如果它不是晚绑定,它就不是多态
什么是多态性:
对象的多态性:父类的引用指向子类的对象;(或子类的对象赋给父类引用)
多态的使用
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但是在运行期,我们实际执行的是子类重写父类的方法。
总结:编译,看左边;运行,看右边。
class Person{ public void eat(){ System.out.print("吃饭"); } } class Man extands Person{ public void eat(){ System.out.print("男孩子吃饭"); } } public class personTest{ public static void main(String[] args){ Person p = new Man;//创建的对象指向为Person p.eat;//此时调用的方法为子类中重写的方法; } }
多态的使用:当调用子父类同名同参数的方法是,实际执行的是子类重写父类的方法---->
[下面详细]
;
多态性的使用前提:
-
类的继承前提;
-
方法的重写;
多态使用举例:
举例1:
/* * 多态性的举例 */ public class PolymorphismText { public static void main(String[] args) { PolymorphismText text = new PolymorphismText(); text.func(new Dog()); text.func(new Cat()); } public void func(Animal animal) { animal.eat(); animal.shout(); } } class Animal { public void eat() { System.out.println("吃"); } public void shout() { System.out.println("叫"); } } class Dog extends Animal { @Override public void eat() { System.out.println("狗吃骨头"); } @Override public void shout() { System.out.println("汪汪汪"); } } class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃老鼠"); } @Override public void shout() { System.out.println("喵呜喵呜"); } }
举例2:
Class Order{ public void method(Object obj){ } }
举例3:
class Driver{ public void doDate(Connection conn){ //conn = new MySQlConnection(); //规范步骤 } }
多态性不适用于属性:
class Person{ int id; } class Man extends Person{ int id; } public class PersonText{ public static void main(String[] args){ Person p = new Person(); p.id;//调用的是Person中的 } }
对象的多态性只适用于方法,不适用于属性(编译运行都看左边)
虚拟方法调用:
概念:子类中定义了与父类同名同参数的方法,在多态的情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态的调用了属于子类的该方法。这样的方法调用在编译期是无法确定的。
多态是编译时行为还是运行时行为?如何证明?
运行时行为;
证明
import java.util.Random; public class PolymorphismText { public static void main(String[] args) { int key = new Random().nextInt(2); System.out.println("key = " + key); Animal animal = getInstance(key); animal.eat(); } public static Animal getInstance(int key) { switch (key) { case 0: return new Cat(); default: return new Dog(); } } } class Animal { public void eat() { System.out.println("吃"); } } class Dog extends Animal { @Override public void eat() { System.out.println("狗吃骨头"); } } class Cat extends Animal { @Override public void eat() { System.out.println("猫吃老鼠"); } }
instanceof 运算符
有了对象多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类中特有的属性和方法不能调用。
如何才能调用子类特有的属性和方法?
向下转型(使用instanceof进行判断):使用强制类型转换符。向上转型:多态
class Man{} class Boy extends Man{} public static void main(String[] args){ Man p2 = new Boy(); Boy m1 = (Boy)p2; }
使用强制转换时可能出现ClassCastException的异常
所以引用了instanceof
instanceof 的使用:
//a instanceof A:判断对象a是否时类A的实例。如果是,返回true,如果不是,返回false。 class Man{} class Boy extends Man{} public static void main(String[] args){ Man p2 = new Boy(); if(p2 instanceof Man){ Boy m1 = (Boy)p2; }//为了避免ClassCastException的异常,我们在向下转型时,先进行instanceof的判断,一旦返回true,就进行向下转型,如果返回false,则不进行向下转型。 }
如果a instanceof A返回true,则a instanceof B也返回true,则类B是类A的父类。