• 【JAVA】关于向上转型与向下转型


    向上转型:

      子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口

            如果子类重写了父类的方法,就根据这个引用指向调用子类重写的这个方法,不是调用父类的,,这个调用过程就称为“动态绑定”。

          ”动态绑定“的意义:如果父类是接口意味则父类是没办法实现方法的,必须要子类去实现,这时如果发生了向上转型,如果不实行动态绑定的话,子类就会陷入无方法可用的困境。而采用动态绑定的话,子类就算发生了向上转型也能实现重写的方法,而则恰恰是接口存在的意义。而代理功能就刚好是这种模式。

    示例代码

    public class UpClass {
    	public static void main(String[] args) {
    	       /*这里注意调用的是子类的构造方法
    		Animal aBird = new Bird();
                等价于
                    1.new Bird();  这里调用父类的构造方法,然后再调用子类自己的构造方法
                    2.Aniaml aBird = 子类的引用 
    		*/
    
    	    Animal aBird = new Bird();
    
    	    aBird.eat();//注意这里调用的是子类的方法,不是父类的,因为重写了父类的eat()方法
    
    		//aBird.fly();错误,向上转型会丢失子类方法
    
    		System.out.println("-----------------");
    		
    		Animal animal = new Animal();
    		animal.eat();
    		
    	}
    }
    
    class Animal{
    	public Animal() {
    		System.out.println("Animal initialization");
    	}
    	public void eat() {
    		System.out.println("animal eat");
    	}
    }
    
    class Bird extends Animal{
    	public Bird() {
    		System.out.println("Bird initialization");
    	}
    	@Override
    	public void eat() {
    		System.out.println("bird eat");
    	}
    	public void fly() {
    		System.out.println("bird can fly");
    	}
    }
    
    
    
    
    结果:
    Animal initialization
    Bird initialization
    bird eat
    -----------------
    Animal initialization
    animal eat
    
    Animal aBird = new Bird();
    就是一个典型的向上转型,子类对象当成父类对象,只能调用父类的成员
    
    注意:
    如果子类重写了父类的方法,就根据这个引用指向调用子类重写的这个方法,不是调用父类的,在上例子表示为调用Bird.eat(),而不是Animal.eat(),这个方法就是覆盖override)。这个调用过程就称为“动态绑定”。
    
    某种程度上来说,向上转型能且只能调用子类的两种方法,,一是子类的构造方法,二是子类重写父类的方法
    
    向上转型时,父类指向子类引用对象会遗失除与父类对象共有的其他方法,也就是在转型过程中,子类的新有的方法都会遗失掉,在编译时,系统会提供找不到方法的错误。在上例中aBird.fly()出现错误就是这个原因

    向下转型:

      父类引用的对象转换为子类类型称为向下转型。

    复制代码

     1 public class Person {
     2     public void smile(){
     3         System.out.println("Person smile!");
     4     }
     5 }
     6 
     7 class Girl extends Person{
     8     public void smile() {
     9         System.out.println("Girl smile!");
    10     }
    11 
    12     public void sing(){
    13         System.out.println("Girl sing!");
    14     }
    15 }
    16 
    17 class main{
    18     public static void main(String[] args) {
    19         Person person=new Girl(); //向上转型
    20         person.smile();
    21 
    22         Girl girl=(Girl)person;    //向下转型,编译和运行皆不会出错
    23         girl.smile();
    24         girl.sing();
    25 
    26         Person person1=new Person();
    27         //Girl girl1=(Girl)person1; //不安全的向下转型,编译无错但会运行会出错
    28         //girl1.smile();
    29         //girl1.sing();
    30 
    31         if(person1 instanceof Girl){
    32             Girl girl1=(Girl)person1;
    33             girl1.smile();
    34             girl1.sing();
    35         }
    36 }        

    复制代码

    在向下转型过程中,分为两种情况:

    情况一:如果父类引用的对象引用的是指向的子类对象,那么在向下转型的过程中是安全的。也就是编译是不会出错误的。

    情况二:如果父类引用的对象是父类本身,那么在向下转型的过程中是不安全的,编译不会出错,但是运行时会出现java.lang.ClassCastException错误。它可以使用instanceof来避免出错此类错误。



    总结:

      1、父类引用可以指向子类对象,子类引用不能指向父类对象。

      2、把子类对象直接赋给父类引用叫向上转型,向上转型不用强制转型。

         如Father father = new Son();

      3、把指向子类对象的父类引用赋给子类引用叫向下转型,要强制转型。

         如father就是一个指向子类对象的父类引用,把father赋给子类引用son 即Son son =(Son)father;

         其中father前面的(Son)必须添加,进行强制转换。

      4、向上转型会丢失子类特有的方法,但是子类重写父类的方法,子类方法有效;

      5、向上转型的作用,减少重复代码,父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁

  • 相关阅读:
    系统吞吐量(TPS)、用户并发量、性能测试概念和公式
    javascript 匿名函数和闭包
    构建高可扩Web架构和分布式系统实战
    Javascript prototype 的作用
    myeclipse下载地址
    tomacat7.0配置(windows)
    IEEE802.11
    C#(多态)
    C#(泛型集合的使用)
    C#(对象引用)
  • 原文地址:https://www.cnblogs.com/jeasion/p/10758351.html
Copyright © 2020-2023  润新知