多态基础的学习
多态的基础语法:
1.向上转型(自动类型转换的意思)
子----->父
2.向下转型(强制类型转换的意思)
父----->子
注意:
Java中允许向上转型,也允许向上转型
无论是向上转型还是向下转型,两种类型之间必须有继承关系
3.多态指的是:
父类型引用指向子类型对象
包括编译阶段和运行阶段
编译阶段:绑定父类的方法
运行阶段:动态绑定子类型对象的方法
4.什么时候向下转型?
如果想访问的方法是子类中特有的方法,此时使用向下转型
创建Animal类
public class Animal {
public void move(){
System.out.println("动物在移动");
}
}
创建Bird类
public class Bird extends Animal{
public void move(){
System.out.println("鸟儿在飞翔");
}
public void eatWorm(){
System.out.println("鸟儿在吃虫");
}
}
创建Cat类
public class Cat extends Animal{
public void move(){
System.out.println("猫在走猫步");
}
public void catchMouse(){
System.out.println("猫在抓老鼠");
}
}
创建测试类Test01
public class Test01 {
public static void main(String[] args){
Animal a1=new Animal();
a1.move();
Cat c1=new Cat();
c1.move();
Bird b1=new Bird();
b1.move();
System.out.println();
//父类型的引用允许指向子类型的对象
//向上转型
Animal a2=new Cat();
//调用a2的move()方法
a2.move();//输出“猫在走猫步”
Animal a3=new Cat();
Cat x=(Cat)a3;
x.catchMouse();//“猫在抓老鼠”
Animal a4=new Bird();
if(a4 instanceof Cat){//判断是否为猫
Cat y=(Cat)a4;
y.catchMouse();//“猫在抓老鼠”
}else if(a4 instanceof Bird){//判断是否为鸟
Bird y=(Bird)a4;
y.eatWorm();//“鸟在吃虫”
}
}
}
程序输出结果:
动物在移动
猫在走猫步
鸟儿在飞翔
猫在走猫步
猫在抓老鼠
鸟儿在吃虫
分析a2.move();
java编译阶段:
对于编译器来说,编译器只知道a2的类型是Animal,所以编译器在检查语法的时候,会去Animal.class字节码文件中找move()方法,找到了,绑定上move()方法,编译通过,静态绑定成功。(编译阶段属于静态绑定)
运行阶段:
运行阶段的时候,实际上是在堆内存中创建的java对象是Cat对象,所以move的时候,真正参与move的对象是一只猫,所以运行阶段会动态执行Cat对象的move()方法。这个过程属于运行绑定阶段。(运行阶段绑定属于动态绑定)
多态表示多种形态:
编译的时候是一种形态
运行的时候是另一种形态
分析向下转型:
Animal a3=new Cat();
注意:只有编译通过的代码才能运行!
提问:a3.catchMouse();这样可以吗?
答案:不可以!
因为:编译器只知道a3的类型是Animal,去Animal.class中找不到catchMouse方法
所以:a3.catchMouse();这样编译会报错
现在必须要向下转型了(强制类型转换)
Cat x=(Cat)a3;
x.catchMouse();//“猫在抓老鼠”
向下转型有风险吗?
Animal a4=new Bird();//表面上a4是一个Animal,运行的时候实际上是个鸟
Cat y=(Cat)a4; //编译无错,运行阶段Bird不能转换成Cat
//运行后会出现java.lang.ClassCastException这样的错
y.catchMouse();
怎么避免java.lang.ClassCastException这样的错?
使用运算符:instanceof
第一:instanceof可以在运行阶段判断动态引用指向对象的类型
第二:语法:(引用 instanceof 类型)
第三:instanceof运算符的结果只能是:true/false
第四:
假设(c instanceof Cat)为true表示:c引用指向的堆内存中的java对象是一个Cat
假设(c instanceof Cat)为false表示:c引用指向的堆内存中的java对象不是一个Cat
任何时候,对类型向下转型时,一定要使用instanceof 运算符进行判断(java规范要求)
Animal a4=new Bird();
if(a4 instanceof Cat){//判断是否为猫
Cat y=(Cat)a4;
y.catchMouse();//“猫在抓老鼠”
}else if(a4 instanceof Bird){//判断是否为鸟
Bird y=(Bird)a4;
y.eatWorm();//“鸟在吃虫”
}