java中的多态
两个重要概念: 1,向上转型 (子类到父类) 2,向下转型(父类到子类)
java允许以上两种类型,且两种类型之间必须有继承关系。
什么是多态: 多种形态(编译和运行是两种形态),多种状态。
父类型引用指向子类型对象(编译阶段静态绑定父类型方法,运行阶段动态绑定子类型对象的方法)
java程序分为编译阶段和巡行阶段。
编译阶段:编译器在检查语法的时候,会静态绑定(编译阶段不会new对象) 即找到父类中和子类同名的方法,并进行静态绑定。编译通过。
运行阶段:在堆内存中实际创建的是子类的对象,所以在调用方法的时候,实际调用的是子类的方法,这个过程属于运行阶段绑定。(运行阶段绑定属于动态绑定)
****什么时候向下转型,当父类型的引用想访问子类型中特有的方法的时候,此时就必须进行向下转型。
class Animal{ public void move(){ System.out.println("animal is moving"); } } class Cat extends Animal{ public void move(){ System.out.println("cat is catching the mouth"); //此处为方法覆盖 } public void walk(){ System.out.println("cat is walking"); } } class Bird extends Animal{ public void move(){ System.out.println("bird is flying"); //此处也是方法覆盖override 覆盖的是Animal中的move方法 } } public class DtTest{ public static void main(String[] args){ Animal cat = new Cat(); //此处就是动态绑定,即在编译阶段,声明一盒animal类型的变量cat,并不生成对象,因为在Animal中有move对象,所以可以编译通过 cat.move(); Animal bird = new Bird(); //在运行阶段,会在堆内存中生成cat对象,且在实际运行的时候 实际是调用cat类的(子类的)move方法。 bird.move(); Animal cat1 = new Cat(); //cat1.walk(); //错误: 找不到符号 Cat x = (Cat)cat1; //此处就是强制类型转换,专业术语为向下转型,一般情况下,强制类型转化多称呼与基本数据类型的时候。 x.walk(); } }
java中的向下转型风险
instanceof运算符:可在运行阶段动态判断
1,instanceof可以在运行阶段动态判断引用指向的对象的类型。
2,语法为 a instance b 返回的为 true 和 false 即判断 a引用指向的堆内存中的java对象是不是一个b类型的类
注意:任何时候只要有强制类型转换一定要使用instanceof进行判断。
class Animal{ public void move(){ System.out.println("animal is moving"); } } class Cat extends Animal{ public void move(){ System.out.println("cat is catching the mouth"); //此处为方法覆盖 } public void walk(){ System.out.println("cat is walking"); } } class Bird extends Animal{ public void move(){ System.out.println("bird is flying"); //此处也是方法覆盖override 覆盖的是Animal中的move方法 } } public class DtTest{ public static void main(String[] args){ Animal cat = new Cat(); //此处就是动态绑定,即在编译阶段,声明一盒animal类型的变量cat,并不生成对象,因为在Animal中有move对象,所以可以编译通过 cat.move(); Animal bird = new Bird(); //在运行阶段,会在堆内存中生成cat对象,且在实际运行的时候 实际是调用cat类的(子类的)move方法。 bird.move(); Animal cat1 = new Cat(); //cat1.walk(); //错误: 找不到符号 Cat x = (Cat)cat1; //此处就是强制类型转换,专业术语为向下转型,一般情况下,强制类型转化多称呼与基本数据类型的时候。 x.walk(); //Animal cat2 = new Cat(); //Bird bird1 = (Bird)cat2; //bird1.walk(); Animal bird1 = new Bird(); if(bird1 instanceof Cat){ Cat c = (Cat)bird1; //此时就是可以编译通过,但是运行时错误。 因为cat和bird两个类之间是没有继承的 c.walk();} //(向下转型风险)Exception in thread "main" java.lang.ClassCastException: class Bird cannot be cast to class Cat (Bird and Cat are in unnamed //module of loader 'app') //at DtTest.main(DtTest.java:41) }//此时就是可以编译通过,但是运行时错误。 因为cat和bird两个类之间是没有继承的 }
//instanceof的用到,解决未知的对象类型 public class DtTest1{ public static void main(String[] args){ Animal x = new Cat(); Animal y = new Bird(); if(x instanceof Cat){ Cat c = (Cat)x; c.walk(); }else if(x instanceof Bird){ Bird b = (Bird)x; b.sing(); } if(y instanceof Cat){ Cat c = (Cat)y; c.walk(); }else if(y instanceof Bird){ Bird b = (Bird)y; b.sing(); } } }