zoukankan      html  css  js  c++  java
  • 【Java学习】向上和向下转型

    https://blog.csdn.net/HuoYiHengYuan/article/details/84855069

    向上转型:将子类转化为父类。

    向下转型:将父类转化为子类。

    继承准备

            下面我们通过例子让读者一步步带入:

            转型是基于继承,所以先实现一个子类继承父类。

    1.  
      /**
    2.  
      * 父类
    3.  
      */
    4.  
      class Father {
    5.  
      String name = "爸爸";
    6.  
      public void sleep() {//睡觉方法
    7.  
      System.out.println(name + "睡觉");
    8.  
      }
    9.  
      }
    10.  
      /**
    11.  
      * 子类继承父类
    12.  
      */
    13.  
      class Son extends Father {
    14.  
      String name = "儿子";
    15.  
      public void p() {//调皮方法
    16.  
      System.out.println(name + "调皮");
    17.  
      }
    18.  
      }

    表现形式

    向上转型

    1.  
      public class UpAndDown {
    2.  
      public static void main(String[] args) {
    3.  
      // 向上转型:将父类引用指向子类对象
    4.  
      Father f = new Son();
    5.  
      f.sleep();//输出“爸爸睡觉”
    6.  
       
    7.  
      //如果f.p();编译出错,不可执行。因为p()不是Father的方法。
    8.  
      }
    9.  
      }

            虽然f是Son对象向上转型得到的,但因为它此时属于Father类,并未实现子类的p()方法,所以不能使用f.p();此时可以看做是一种“瘦身”。

    向下转型

            还是上面的例子,如果再强转为子类。代码如下。

    1.  
      public class UpAndDown {
    2.  
      public static void main(String[] args) {
    3.  
      // 向下转型
    4.  
      Father f = new Son();
    5.  
      ((Son)f).P();//输出“儿子调皮”
    6.  
      }
    7.  
      }

            是不是很惊喜?父类转化为子类,又恢复了子类独有的方法。

            那么,如果我们是直接向下转型呢?

    1.  
       
    2.  
      public class UpAndDown {
    3.  
      public static void main(String[] args) {
    4.  
      // 直接向下转型
    5.  
      Father f = new Father();
    6.  
      f.sleep();//输出“爸爸睡觉”
    7.  
      ((Son)f).P();//报错!!!!!!!!!!
    8.  
      }
    9.  
      }

    看来,向下转型并不耽误父类方法的调用。

    但是,直接向下转型竟然会报错!提示如下:

    Exception in thread "main" java.lang.ClassCastException: lanqiao.Father cannot be cast to lanqiao.Son
        at lanqiao.UpAndDown.main(UpAndDown.java:7)

    意思是说:类型转换异常,Father不能转化为Son。

    这种现象我们可以通俗地理解:

    • 向上转型可以当做隐藏自身的方法,所以,再转回来(向下转型)方法就会恢复原状。该是你的还是你的。
    • 直接向下转型,父类不具有子类的独有方法,所以即使转化成功,也是个残废儿子,还不如不转,所以直接报错转化失败。不是你的你想都别想。

     其实吧,事情是这样的:

    内存中,因为向上转型是父类的引用指向为子类的对象,所以,它只是指向了父类应该拥有的属性和方法,而子类的独有的方法和属性就不指向了(或者说隐藏了),当再强转到子类时。又重新指向了子类对象,那属于它的东西又恢复了。

    来图:


            好了,那么转型有撒子用途呢?

    向上转型和向下转型的使用

    向上转型

    我们这样理解,人都能跳舞,男人和女人跳舞是不一样的。(女装大佬请手下留情!)

    假装有代码:

    假设Person有个dance()跳舞方法。

    Man extends Person      Women extends Person

    此时Man和Women都重写了Person的dance();

    当 Person p = new Man(); p.dance(); //这个时候就是调用男人跳舞的dance方法
    当 Person p = new Woman(); p.dance();// 这个时候就是调用女人的跳舞的dance方法

    这样其实就是一个java的继承,多态. 利于程序扩展. 你需要理解这种设计方式,会让你写出更易维护,简洁的代码。

    向下转型

    灵感不够,拷贝来凑:(不要揍我)

    https://blog.csdn.net/xyh269/article/details/52231944

    package com.company.electronics;
    
    /**
     * @author dxx
     * @date 2020/9/12 10:13
     */
    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 h = new Male();// 向上转型
            doSleep(new Male());//此处匿名子类对象,当然实际应用时应该是用上面的向上转型公式,然后将子类对象传递进来,这样以后好在向下转型,此处没有向下转型,所以直接用了匿名类对象。
            doSleep(new Female());
    
        }
    }
    
    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..");
        }
    
    }
    View Code

    https://www.cnblogs.com/buptldf/p/4959480.html

    package com.company.electronics;

    /**
    * @author dxx
    * @date 2020/9/12 10:13
    */
    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 h = new Male();// 向上转型
    doSleep(new Male());//此处匿名子类对象,当然实际应用时应该是用上面的向上转型公式,然后将子类对象传递进来,这样以后好在向下转型,此处没有向下转型,所以直接用了匿名类对象。
    doSleep(new Female());

    }
    }

    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..");
    }

    }
  • 相关阅读:
    调用匿名函数的骚操作
    angular,vue,react的父子通信
    JavaScript高阶函数的应用
    图解javascript中this指向
    前端开发必备
    MEAN-全栈javascript开发框架
    MongoDB初识
    ES6新特性概览
    为什么是link-visited-hover-active
    CSS布局 — 圣杯布局与双飞翼布局
  • 原文地址:https://www.cnblogs.com/gtea/p/13697699.html
Copyright © 2011-2022 走看看