Java向上转型与向下转型知识点整理
本篇博客的由来是自己对于java多态里的向上转型与向下转型概念及用法不明了,所以查询资料整理如下所示,参照了许多大神的写法,终有所掌握。
概念
Java中的继承机制使得一个类可以继承另一个类,继承的类称为子类,被继承的类称为父类。
向上转型:父类的引用指向子类对象,自动进行类型转换。换言之,子类对象转为父类,其中父类可以是接口。
公式: <父类型> <引用变量名> = new <子类型>();
即 Father f = new Son();Father是父类或接口,Son是子类。
向下转型:将一个指向子类对象的父类引用赋给一个子类的引用,即:父类类型转换为子类类型。需强制类型转换。换言之,父类对象转为子类(为了将向上转型的对象还原)。
公式:<子类型> <引用变量名> = (<子类型> )<父类型的引用变量>;
即 Father f; Son s = (Son)f;
代码块
向上转型
public class Main { public static void main(String[] args) { Animal animal = new Dog(); //向上转型 animal.eat(); //狗吃骨头 animal.run();// warn!向上转型后父类引用不能调用子类自己的方法, 调用run方法会报错 }}class Animal { public void eat(){ System.out.println("animal"); }}class Dog extends Animal{ public void eat(){ System.out.println("狗吃骨头"); } public void run(){ System.out.println("狗追猫,追不上,摔了一跤"); }}
分析:这里用到了向上转型,换言之,就是用父类的引用变量去引用子类的实例,这是允许的。当向上转型之后,父类引用变量可以访问子类中属于父类的属性和方法,但是不能访问子类独有的属性和方法。
案例中由于子类重写了父类的 eat() 方法,所以调用的 eat() 方法是子类的 eat() 方法,输出结果为:“狗吃骨头”;然而当调用子类独有的 run() 方法时会报错。
向下转型
并不是所有的对象都可以向下转型,只有当这个对象原本就是子类对象通过向上转型得到的时候才能够成功转型。
Animal animal= new Dog();Dog dog = ((Dog) animal);
分析:上述代码是允许的,因为animal引用的对象原本就是Dog对象向上转型得到的,在对animal向下转型后得到的还是Dog类的对象,能够被Dog类的引用变量引用。
如果还有一个Cat类继承了Animal类,然后实例化Dog类,并新建一个Animal类的引用变量“animal”引用该实例,然后新建一个Cat类的引用变量,引用向下转型的“animal”变量,代码如下:
Animal animal= new Dog();Cat cat= (Cat) animal;
分析:上述代码在运行的时候会报错,因为animal对象是由Dog对象向上转型得到的,只能够向下转型成Dog对象,不能够向下转型成Cat对象。
转型的好处
代码如下:
class Fruit{public void show() {System.out.println("this is a fruit");}}class Apple extends Fruit{ public void show() {System.out.println("this is a apple"); } public void test() {System.out.println("i am a apple"); }}class Orange extends Fruit{ public void show() {System.out.println("this is a Orange"); } public void test() {System.out.println("i am a Orange"); }}public static void run(Fruit fruit) {//假设在主类中定义了一个run()方法,该方法传入一个Fruit参数,并调用了Fruit对象的show()方法,fruit.show();}public static void main(String[] args) { run(new Fruit()); run(new Apple()); run(new Orange());}
分析:上述代码中,调用run()方法时的参数不仅是Fruit对象,也可以是Apple对象和Orange对象,当传入的是Apple对象和Orange对象时,就会向上转型成Fruit对象,但是调用的show()方法还是Apple对象和Orange对象的show()方法。这样就不需要在主类中同时重载三个run()方法,减少了代码量。