首先我们定义一个动物类
该类只有一个“move”的方法
package polymorphism;
public class Animal {
public void move() {
System.out.println("动物在移动!");
}
}
其次我们定义一个小鸟类
该类继承动物类,并且重写“move”方法
package polymorphism;
public class Bird extends Animal{
public void move() {
System.out.println("鸟儿在飞翔!");
}
public void fly() {
System.out.println("flyyyyyyyyyyyy!");
}
}
最后定义一个小猫类
package polymorphism;
public class Cat extends Animal {
//重写父类中继承的方法
public void move() {
System.out.println("猫咪在走猫步!");
}
//子类特有的方法
//不是说所有动物都可以抓老鼠
public void catchMouse() {
System.out.println("猫抓老鼠");
}
}
我们知道:
面向对象的三大特征
*封装性
*继承性
*多态性
关于java语言当中的多态机制
1.Animal、Bird、Cat三个类之间的关系
Cat继承Animal
Bird继承Animal
Cat和bird没关系
2.多态中涉及的概念
*向上转型(upcasting)
子类型–>父类型
自动类型转换
向上转型只要编译通过就可以运行
*向下转型(downcasting)
父类型–>子类型
强制类型转换【强制类型转换符】
当调用的方法是子类型中特有的,父类中不存在,需向下转型
*注意
两种类型之间必须有继承关系,没有继承关系,编译报错
使用多态机制
1.Animal和Cat之间存在继承关系
2.Cat is an animal【合理】
3.对象类型是Cat,引用的数据类型是Animal,进行了类型转换
4.父类型引用指向子类型对象
5.程序在编译时a2引用的数据类型为Animal,由于Animal.class字节码
当中有move方法,编译才会通过
这个过程我们称为静态绑定(编译阶段绑定)
6.程序在运行阶段,JVM堆内存中真实创建的对象是Cat对象,
所以在运行的时候调用的是Cat的move方法
这个过程我们称为动态绑定(运行阶段绑定)
7.父类型引用指向子类型对象这种机制导致程序存在
编译阶段绑定和运行阶段绑定两种不同的形态/状态。
这种机制可以成为一种多态语法机制
接下来我们编写一个测试类
对我们刚才创建的各个类进行测试
package polymorphism;
public class Test {
public static void main(String[] args) {
//旧方法
Animal a1 = new Animal();
a1.move();//动物在移动!
Bird b1 = new Bird();
b1.move();//鸟儿在飞翔!
Cat c1 = new Cat();
c1.move();//猫咪在走猫步!
c1.catchMouse();//猫抓老鼠
Animal a2 = new Cat();
a2.move();//猫咪在走猫步!
//a2.catchMouse();//编译报错:,没有为Animal定义catchMouse方法
Cat c2 = (Cat) a2;
c2.catchMouse();//猫抓老鼠
//父类型引用指向子类型对象【多态】
Animal a3 = new Bird();
/**
1.编译器检查到a3的数据类型是Animal,和Cat之间存在继承关系,
该语法符合向下转型
2.运行阶段出现异常,因为JVM堆内存中真实存在的对象是Bird类型,
Bird无法转换成Cat对象,
此时出现著名异常:java.lang.ClassCastException【类型转换异常】
这种异常通常在【向下转型】时发生
3.以上异常只有在强制类型转换时发生,也就是说【向下转型】存在隐患
4.怎样避免java.lang.ClassCastException【类型转换异常】呢
使用instanceof运算符
(1)语法格式
(引用 instanceof 数据类型名)
(2)执行结果
true/false
(3)假设(a instanceof Animal)
true:
a这个引用指向对象是Animal类型
false:
a这个引用指向对象不是Animal类型
5.java语言规范要求
在进行强制类型转换之前,建议采用instanceof运算符进行判断,
避免出现
java.lang.ClassCastException【类型转换异常】
*/
//Cat c3 = (Cat) a3;//编译通过,运行失败
System.out.println("----------");
if(a3 instanceof Cat){//a3是一个Cat类型对象
Cat c3 = (Cat) a3;
c3.catchMouse();
}
else if(a3 instanceof Bird) {//a3是一个Bird类型对象
Bird b2 = (Bird) a3;
b2.fly();//flyyyyyyyyyyyy!
}
}
}
结果一目了然:
多态的作用
1.降低耦合度,提高扩展力
2.尽量使用
3.父类型引用指向子类型对象
核心:面向抽象编程,不要面向具体编程