多态的基础语法:
举例
Animal.java
//动物类: 父类
public class Animal {
//移动的方法
public void move(){
System.out.println("动物在移动");
}
}
Dog.java
//狗类: 子类
public class Dog extends Animal{
//移动的方法(覆盖)
public void move(){
System.out.println("狗在狂奔");
}
}
Bird.java
//鸟类: 子类
public class Bird {
//移动的方法(覆盖)
public void move(){
System.out.println("鸟在飞翔");
}
public void catchInsect(){
System.out.println("鸟儿在抓害虫");
}
}
测试类
public class Test {
public static void main(){
Animal a1 = new Animal();
a1.move();
Dog d1 = new Dog();
d1.move();
Bird b1 = new Bird();
b1.move();
}
}
-
学习基础语法之前, 要知道:
- **向上转型** - 子类 ---> 父类 (类似自动类型转换) - **向下转型** - 父类 ---> 子类(类似强制类型转换,需要强制类型转换符) tips : Java中允许向上转型和向下转型, **但是两种类型之间必须有继承关系**,没有继承关系编译会报错
public class Test {
public static void main(){
//向下转型
//a2,a3是父类型的引用
//new Dog/Bird是子类型的对象
Animal a2 = new Dog();
Animal a3 = new Bird();
//调用move方法
//多态: 多种形态, 多种状态
a2.move();
a3.move();
}
}
其运行结果是: 狗在狂奔 鸟在飞翔
而不是Animal中的move方法
分析:
对Java来说, 程序分为编译阶段和运行阶段
编译阶段:
- 对编译器来说, 编译器只知道a2的类型为Animal,
所以编译器在检查语法时, 会去Animal.class字节码文件中寻找move()方法
找到后绑定move()方法. 编译通过, 绑定成功(编译阶段属于静态绑定)
运行阶段
- 在运行阶段的时候, 世界上在堆内存中创建的Java对象是Dog或者Bird
所以move的时候,真正参加move的对象是"一条狗"或者"一只鸟". 所以在运行阶段会执行该对象的move()方法. 这个过程属于运行阶段绑定(运行阶段绑定属于动态绑定)
多态: 多种形态,多种状态
编译的时候一种状态, 运行的时候又一种状态
如: 父类型引用指向子类型对象
编译阶段: 静态绑定父类的方法
运行阶段: 动态绑定子类型对象的方法
不能这样用
如下引用抓害虫的方法
public class Test {
public static void main(){
Animal a4 = new Bird();//对象是一只猫
a4.catchInsect();//编译会报错不通过
}
}
分析:
在编译阶段会去Animal.class中寻找catchInsect()方法, 但是该方法是鸟类独有的, 找不到. 编译不通过,报错.
但是如果就是想这样调用catchInsect()方法, 有没有什么办法呢?
有!!!
什么时候用到 向下转型?
当向上转型后要访问的方法是子类中独有的方法, 必须使用向下转型
public class Test {
public static void main(){
Animal a4 = new Bird();//对象是一只猫
//a4.catchInsect();//编译会报错不通过
//以下为向下转型
//a4为Animal类,转成Bird类
//编译通过,可运行
Bird b2 = (Bird)a4;
b2.catchInsect();
}
}