• 向上转型和向下转型


    简单使用

    声明一个父类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(); 
    	}
    
    }
    

    输出:

    我是子类  苹果...
    我是子类  苹果...
    我是你的小呀小苹果~~~~~~
    Exception in thread "main" java.lang.ClassCastException: com.sheepmu.Fruit cannot be cast to com.sheepmu.Apple
    at com.sheepmu.Sys.main(Sys.java:30)
    
    

    解释:

    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

  • 相关阅读:
    软件工程个人作业(4)
    软件工程个人作业(3)
    软件工程个人作业(2)
    软件工程个人作业(1)
    构建之法
    消息分发机制,实现战场与UI通信功能
    设置父物体方法(包括层级)
    NGUI通过点击按钮来移动面板位置,实现翻页功能
    unity中调用android的剪切板
    屏蔽UI事件
  • 原文地址:https://www.cnblogs.com/gyyyblog/p/11806601.html
Copyright © 2020-2023  润新知