面向对象三大特征:封装,继承,多态
关于多态中涉及到的几个概念
* 向上转型(upcasting)
子类型——>父类型 又被称为:自动类型转换
* 向下转型
父类型——>子类型 又被称为:强制类型转化【需要加强制类型转换符】
注:无论是向上转型还是向下转型,两种类型之间必须要有继承关系,没有继承关系,程序是无法编译通过的。
以下用代码解释多态语法机制
public class Animal {
public void move(){
System.out.println("动物在移动");
}
}
public class Cat extends Animal{
//重写父类中继承过来的方法
public void move(){
System.out.println("小喵咪在爬行");
}
public void mouse(){
System.out.println("抓老鼠");
}
}
public class Bird {
//重写父类中继承过来的方法
public void move(){
System.out.println("小鸟在飞 ");
}
}
public class Test2 {
public static void main(String[] args) {
Animal a = new Animal();
a.move();
Cat b = new Cat();
b.move();
Bird c = new Bird();
c.move();
//父类型引用指向子类型对象这种机制导致程序存在编译阶段绑定和运行阶段绑定两种不同的
//形态/状态,这种机制可以称为一种多态语法机制
Animal d = new Cat();//Java中允许这种语法,父类型指向子类型对象
d.move();
//java程序永远都分为编译阶段和运行阶段 编译阶段编译器检查d这个引用的数据类型为Animal,由于Animal.class
//字节码当中有move()方法,所以编译通过了,这个过程我们称为静态绑定,编译阶段绑定,只要静态绑定成功之后才有
//后续的运行,在程序运行阶段,JVM堆内存当中真实创建的对象是Cat对象,那么一定会调用Cat对象的move()方法
//此时发生了程序的动态绑定,运行阶段绑定
//Bird d2 = new Cat(); 编译报错,因为两种类型之间不存在任何继承关系,无法向上或者向下转型。
//Cat d1 = new Animal(); 编译报错
//d.mouse(); 编译报错因为Animal.class字节码中没有找到mouse()方法,导致静态绑定失败,即编译失败。
//什么时候需要使用向下转型呢?
//当调用的方法是子类型中特有的,在父类型当中不存在的,必须向下转型
//我们若想以上对象执行mouse()方法,可以进行强制类型转换,将d强制类型转换为Cat类型。
Cat k = (Cat) d;
k.mouse();//抓老鼠
//Animal k1 = new Bird();
//Cat k2 = (Cat) k1;
//Bird对象无法转换成Cat对象,类型转化异常,编译报错
}
}
注:
* 向上转型只要编译通过,运行一定不会出现问题
* 向下转型编译通过,运行可能出错,例如上述代码Bird对象无法转换成Cat对象,类型转换异常
- 如何避免向下转型出现的ClassCastException呢?
使用instanceof运算符可以避免出现以上的异常
* instanceof运算符怎么用?
- 语法格式:
(引用 instanceof 数据类型名)
- 以上运算符的执行结果类型是布尔类型,结果可能是true/false
假设(a instanceof Animal)
true表示:
a这个引用指向的是一个Animal类型
false表示
a这个引用指向的不是一个Animal类型
(Java规范中要求:在进行强制类型转换之前,建议采用instanceof运算符进行判断,避免ClassCastException异常的发生)
* 面向对象编程的核心:定义好类,然后将类实例化为对象,给一个环境驱使一下,让各个对象之间协作起来形成一个系统。
* 多态的作用是什么?
能降低程序的耦合度,提高程序的扩展力
能使用多态尽量使用多态
父类型引用指向子类型对象
核心:面向对象编程,尽量不要面向具体编程。