### 向上转型与向下转型
> 向上转型:将子类转型为父类;
> 向下转型:将父类转型为子类;
![](https://img.kancloud.cn/91/f7/91f753722b51f445021b9c5b25c28470_728x478.png)
#### 向上转型的 **特点**
- 语法
```
<父类型> <引用变量名> = new <子类型>();
```
- 好处:隐藏了子类型,提高了代码的扩展性;
- 坏处:只能使用父类的功能,不能使用子类的特有功能,功能被限定;
- 场景:使用父类的功能即可完成的操作,不需要面对子类类型;
```java
/**
* 向上转型的缺点
*/
public class Car {
/**
* 开车
*/
public void run() {
System.out.println("父类的run()");
}
}
/**
* 蔚来
*/
class Nio extends Car {
@Override
public void run() {
System.out.println("子类的run()");
}
/**
* 汽车的价格
*/
public void price() {
System.out.println("子类汽车的价格");
}
public static void main(String[] args) {
// 习惯
Nio nio = new Nio();
nio.run();
nio.price();
System.out.print("\n");
// 向上转型
Car car = new Nio();
car.run();
// car.price();
}
}
```
运行程序后输出的内容:![](https://img.kancloud.cn/44/38/4438f6876e7ff2604f6406e91f4a995c_294x190.png)
> 使用car实例调用price的时候,提示`Cannot resolve method 'price' in 'Car'`
- 代码中*Car car = new Nio()*,我们使用了向上转型,但是由于进行了向上转型,就失去了使用父类中所没有的方法的“权利”,不能调用price()方法;
- 那向上转型到底有什么用呢?
```java
/**
* 向上转型的优点
*/
public class Car {
/**
* 开车
*/
public void run() {
System.out.println("父类的run()");
}
public void tune(Car car) {
// 插钥匙,拧钥匙,开火,踩离合,加油门,松离合,起步走
car.run();
}
}
class Tesla extends Car{
@Override
public void run() {
System.out.println("Tesla的run()");
}
/**
* 汽车的价格
*/
public void price() {
System.out.println("Tesla汽车的价格");
}
}
/**
* 蔚来
*/
class Nio extends Car {
@Override
public void run() {
System.out.println("Nio的run()");
}
/**
* 汽车的价格
*/
public void price() {
System.out.println("Nio汽车的价格");
}
public static void main(String[] args) {
// 向上转型缺点 - 不能使用子类扩展的price功能
Car car = new Nio();
car.run();
// car.price();
System.out.print("\n");
// 习惯
Nio nio = new Nio();
nio.run();
nio.price();
System.out.print("\n");
// 向上转型的优点
car.tune(nio);
Tesla tesla = new Tesla();
// 方便扩展
car.tune(tesla);
}
}
```
##### 向上转型总结
向上转型虽然使代码变得简洁,体现了JAVA的抽象编程思想,但是也出现了上面提到的子类无法调用其独有的方法,这要怎么解决呢?所以就有了与之对应的向下转型,弥补了向上转型所带来的缺陷。
#### 向下转型
#### 向上转型的 **特点**
- 语法
```
<父类型> <引用变量名A> = new <子类型>();
<子类型> <引用变量名> = (子类型)<引用变量名A>;
```
- 好处:可以使用子类型的特有功能;
- 坏处:向下转型具有风险,容易发生ClassCastException,只要转换类型和对象不匹配就会发生。可以使用关键字instanceof进行解决;
- 场景:泛型类业务;
```java
public class Car {
/**
* 开车
*/
public void run() {
System.out.println("父类的run()");
}
}
class Tesla extends Car {
@Override
public void run() {
System.out.println("Tesla的run()");
}
/**
* 汽车的价格
*/
public void price() {
System.out.println("Tesla汽车的价格");
}
}
class Nio extends Car {
@Override
public void run() {
System.out.println("Nio的run()");
}
/**
* 汽车的价格
*/
public void price() {
System.out.println("Nio汽车的价格");
}
public static void main(String[] args) {
// 先向上转型
Car[] car = { new Nio(), new Tesla() };
car[0].run();
// car[0].price();
// 后向下转型
Nio nio = (Nio)car[0];
nio.price();
// 后向下转型
Tesla tesla = (Tesla) car[1];
tesla.price();
// 不向上转型
Car car2 = new Car();
((Nio)car2).run();
}
}
```
> 如果不先进行`向上转型`,直接实例化Car,进行强制性`向下转型`可以不?
![](https://img.kancloud.cn/1d/24/1d24d16ff0c4d7b561ba49f1c24b6ba8_414x182.png)
编译使未报错,但运行后程序出现错误;
![](https://img.kancloud.cn/17/e5/17e5ff28f08f8e91218f92497c30e141_1900x138.png)
*****
这是因为我们实例化了一个父类对象,当我们使用强制转型转为`Nio`时,由于子类可以定义自己的方法,父类的域小于子类的域,这个时候我们直接向下转型就会发生这个错误,所以需要*先向上转型,后向下转型*。
##### **instanceof**关键字
- 语法
```
# 一个对象是否为一个类的实例
**对象名 instanceof 类名**
```
![](https://img.kancloud.cn/dd/8e/dd8e01ef5d37255a6fb8c980bb33bad8_770x218.png)
*****
### 参考与引用
[CSDN - 迷棱](https://blog.csdn.net/guchenjun789/article/details/81055317)
[CSDN - yddcc](https://blog.csdn.net/weixin_40601536/article/details/84103029)
[CSDN - TNTZS666](https://blog.csdn.net/TNTZS666/article/details/80274526)