Java多态中父类与子类的转换

1、正确的转型和错误的转型

public class TestObjectConvert {
    public static void main(String[] args) {
        test1();
        test2();
    }
    private static void test1() {
        Fruit fruit1 = new Fruit();
        Apple apple1 = new Apple();
        apple1 = (Apple) fruit1; // java.lang.ClassCastException
    }
    private static void test2() {
        Fruit fruit1 = new Apple();
        Apple apple1 = new Apple();
        apple1 = (Apple) fruit1;
    }
    static class Fruit {}
    static class Apple extends Fruit { }
}

结果是:test1:报类转异常;test2:转换正常。结论:所以,想让父类强制转换成子类,不是没有可能,除非父类是子类构造出来的实例,不然是不能强转的。只有先经过向上转型,才能进行向下转型。向上转型会丢失子类的方法。

正确的转型:

Father f1 = new Son(); // upcasting (向上转型)
Son s1 = (Son)f1; // 这就叫 downcasting (向下转型)

错误的转型:

Father f2 = new Father();
Son s2 = (Son)f2; // 出错,子类引用不能指向父类对象

2、向上转型时如何调用方法

package testP.test;
class Person {  
    public void eat(){
        System.out.println("Person eatting...");
    }
    public void sleep() {
        System.out.println("Person sleep...");
    }
}



package testP.test;
public class son extends Person {
    public void eat() {
        System.out.println("son eatting...");
    }
    public void fly() {
        System.out.println("son fly...");
    }
     public static void main(String[] args) {
         Person person = new son();
         person.eat(); // 调用的是son里面的eat方法,son重写了Person父类的方法
         person.sleep(); //调用的是父类person的方法
         person.fly(); //报错了,丢失了son类的fly方法
        }
}

这是因为:向上转型:子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口
向上转型时,父类指向子类引用对象会遗失除与父类对象共有的其他方法,也就是在转型过程中,子类的新有的方法都会遗失掉,在编译时,系统会提供找不到方法的错误。

3、向上转型的好处

package multistate;
public class Human {
    public void sleep() {
        System.out.println("Human sleep..");
    }
    public static  void doSleep(Human h){
        h.sleep(); 
    }//此时传递的参数是父类对象,但是实际调用时传递子类对象,就是向上转型。
    public static void main(String[] args) {
        Human h1 = new Male();// 向上转型
        Human h2 = new Male();// 向上转型
        doSleep(h1);
        doSleep(h2);  
    }
}
class Male extends Human {
    @Override
    public void sleep() {
        System.out.println("Male sleep..");
    }
}
class Female extends Human {
    @Override
    public void sleep() {
        System.out.println("Female sleep..");
    }
}

如果不向上转型则必须写两个doSleep函数,一个传递Male类对象,一个传递Female类对象。这还是两个子类,如果有很多子类呢,就要写很多相同的函数,造成重复.

4、为什么向下转型

向上向下转型的使用场景常见的是在集合类中,比如你有一个父类和N个子类,然后你想把这些子类装进一个集合里面,这个时候你肯定不会为每一个子类都去创建一个集合来分别存储,毕竟这么干会写很多重复的代码,你肯定会用泛型,自然而然的泛型的类型肯定是用父类的类型,因为任何一个子类的类型都不能存储其他兄弟类型,那么在你将各个子类对象塞进集合里的时候,会发生一个自动向上转型的过程,意思就是你塞进去的每个对象都会由一个父类的引用指向他们,向上转型就丢失了子类特有的方法,那么当你从集合里面拿出你的子类实例,这个时候你的子类其实根本无法调用他们作为子类对象的特有的方法,那么有什么办法可以让这些子类找回自己特有的方法呢,那就是向下转型了,这就是基本的向上向下转型的使用场景。

5、多态的实现方式
接口实现、继承父类进行方法重写、同一个类中进行方法重载


版权声明:本文为qq_35784996原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。