向上转型和向下转型

匿名 (未验证) 提交于 2019-12-03 00:17:01

声明一个父类Father,子类Son继承Father

Father a = new Son()  // 父类引用、子类对象(向上转型)  Son b = (Son)a  //  向下转型,强制转换 // 父类引用转成子类引用 
public class Animal {      public void eat(){     System.out.println("animal eatting...");   } } class Bird extends Animal{      public void eat(){     System.out.println("bird eatting...");   }      public void fly(){          System.out.println("bird flying...");   } } class Main{      public static void main(String[] args) {          Animal b=new Bird(); //向上转型     b.eat(); // 调用的是子类eat()     //! error: b.fly();     //  b虽指向子类对象,但此时子类作为向上转型的代价丢失和父类不同的fly()方法------     dosleep(new Male());     dosleep(new Female());   }      public static void dosleep(Human h) {     h.sleep();   } }
public class Human {   public void sleep() {     System.out.println("Human sleep..");   } } 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..");   } }

这里就可以看出向上转型的好处和使用场景了

public static void dosleep(Human h) {     h.sleep(); }

这里的参数类型是父类,传入的值是子类,这就完成了向上转型操作。然后会自动判断调用该子类的对应方法。试想,如果我们这么干

public static void dosleep(Male male) {     male.sleep(); }  public static void dosleep(Female fe) {     fe.sleep(); }  ......

这是人,要换成水果,给你来个几百种,不写死才怪。
因此向上转型很好的简化了代码,也正是体现了java的抽象编程思想,使代码变得解耦。

class Fruit   {     public void myName()     {         System.out.println("我是父类  水果...");     } }   class Apple extends Fruit {      @Override     public void myName()      {          System.out.println("我是子类  苹果...");     }     public void myMore()     {         System.out.println("我是你的小呀小苹果~~~~~~");     } }   public class Sys{      public static void main(String[] args) {          Fruit a=new Apple(); //向上转型         a.myName();                  Apple aa=(Apple)a; //向下转型,编译和运行皆不会出错(正确的)         aa.myName();//向下转型时调用的是子类的         aa.myMore();;                    Fruit f=new Fruit();         Apple aaa=(Apple)f; //-不安全的---向下转型,编译无错但会运行会出错         aaa.myName();         aaa.myMore();      }  }

输出:

 

解释:

  1. 正确的向下转型
        Fruit a=new Apple(); //向上转型         a.myName();                  Apple aa=(Apple)a; //向下转型,编译和运行皆不会出错(正确的)         aa.myName();//向下转型时调用的是子类的

a指向子类的对象,所以子类的实例aa也可以指向a

向下转型后因为都是指向子类对象,所以调用的当然全是子类的方法

  1. 错误的向下转型
        Fruit f=new Fruit();         Apple aaa=(Apple)f; //-不安全的---向下转型,编译无错但会运行会出错         aaa.myName();         aaa.myMore(); 

这里f指向父类对象,子类实例肯定不能指向f

3.Java为了解决不安全的向下转型问题,引入泛型的概念

4.为了安全的类型转换,最好先用 if(A instanceof B) 判断一下对象类型

例:

if (f instanceof Apple){     Apple aaa=(Apple)f;         aaa.myName();         aaa.myMore();  }

参考文章:https://blog.csdn.net/sheepmu/article/details/38327205

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!