# 多态
[TOC]
从某种意义上来讲,封装和继承都是为了多态而准备的
在Java中多态性分为两种不同的展现形式
## 方法的多态性(编译时多态)
前面我们在两处地方提到了方法的多态性,一是方法的重载,还有就是方法的重写
>[info] 方法重载的多态性的意义在于一个方法名称有不同的实现;
> 方法重写多态性的实现在于,父类的一个方法,不同的子类可以有不同的实现
## 对象的多态性(运行时多态)
我们在Java程序中说的多态大多指的是运行时多态,所以我们后面直接用多态来称呼
>[warning] Java引用类型变量有两种类型:一种是编译时类型,一种是运行时类型
* 编译的类型是由声明变量的时候确定的
* 运行时的类型是由实际上赋给该变量的对象决定的
~~~java
//比如声明变量类型为Animal,实际赋给该变量的对象类型为Dog
Animal animal = new Dog();
~~~
**如果运行时类型和编译时类型不一致就会出现所谓的多态**
* 首先编译时类型和运行时类型得是父类和子类的关系
* 多态最常用的场景就是子类重写父类方法后,如果引用变量的类型为父类,而对象为子类,如果引用类型调用重写方法,回去执行子类定义的实现
~~~java
public class Test {
public static void main(String[] args) {
//简单的子类继承和实例化对象
/*Dog dog = new Dog();
dog.say();
Cat cat = new Cat();
cat.say();*/
//多态的测试
//父类引用指向Dog子类的具体实现
Animal animal = new Dog();
animal.say();
System.out.println("**********");
// 更换实现
animal = new Cat();
animal.say();
}
}
~~~
## 引用类型的强制类型转换
~~~
public class Animal {
public void say() {
System.out.println("我是一个动物");
}
public void sleep() {
System.out.println("动物在睡觉");
}
}
public class Dog extends Animal {
public void say() {
System.out.println("我是一个狗");
}
public void play() {
System.out.println("狗正在玩");
}
}
public class Test {
public static void main(String[] args) {
//对象的转型
//对象向上转型:子类对象 ->父类对象 安全
Animal animal = new Dog();
animal.say();
animal.sleep();
//对象向下转型 (引用类型的强制类型转换):父类对象——>子类对象 不安全
//向下转型必须发生在向上转型之后,才可以进行向下转型
Dog dog = (Dog) animal;
dog.say();
dog.play();
Cat cat = (Cat) animal;
cat.say();
}
}
~~~
编写Java程序的时候,引用变量只能调用它编译时的方法,而不能调用其运行时的方法,如果你必须要调用其运行时的类型,则需要进行强制类型转换。
强制类型转换实际上是把大的类型转为小的类型。
在我们的引用数据类型里面,大的类型是父类,小的类型是子类。
只可能发生在子类和父类的关系中。
## instanceof运算符
instanceof运算符的前一个操作数一般是引用数据类型的变量,后一个操作数是类名(接口),它是用于判断前面的对象是否是后面的类,或者其子类。如果是的话,返回true;
>[info] instanceof 运算符一般用于在我们对引用数据类型进行强制类型转换之前进行判断使用
> 避免在实际的运行过程中出现classCastException。
~~~
public static void main(String[] args) {
Animal tom = new Dog();
Animal mimi = new Cat();
Animal ani = new Animal();
if(ani instanceof Dog) {
Dog dog = (Dog)ani;
System.out.println("&&");
System.out.println(dog.getAge());
}
if(tom instanceof Dog) {
Dog dog2 = (Dog) tom;
System.out.println("**");
System.out.println(dog2.getAge());
}
}
~~~