Java——超类和子类对象之间的转换

继承是Java中常用的一项特性,通过继承我们可以省去很多麻烦。

而Java中超类和子类对象之间的转换则是很多新手的常遇见的难题,要是处理不好,恐怕会因为这个很特殊的问题导致一些潜在的危险,让你整整一个晚上都在调试程序以解决一个让人抓狂的java.lang.ArrayStoreException异常。 

哈哈,所谓救人一bug胜造七级浮屠,今天我们就来理一理Java中超类和子类对象之间的转换,看看它到底有什么不一样!

首先我们要了解一下转换的概念。

从子类向父类的转换称为向上转换(upcasting),通过向上转换,我们能够在编写程序时采用通用程序设计的思想,在需要使用子类对象的时候,通过把变量定义为父类型,我们可以通过一个变量,使用该父类型的所有子类型实例;从父类型向子类型的转换称为向下转换(downcasting),通过向下转换,我们能在必要的时候,将父类型变量转换成子类型变量,使用一些通过子类型才能够使用的方法。

那什么时候可以进行转换呢?

我们先来说一说向上转换,这个比较简单,而且限制还少。

还是老规矩,我们下面来看一段代码~~

来呀!!阿福,放代码~~~

                        class  Father
    
                       {

                       };

                       class Son extends  publc  Father

                       {    

                       };

                    

                           

在上面的程序中Father为超类,son是father的子类

那如何将子类转换为超类呢?

扫描二维码关注公众号,回复: 3997803 查看本文章
  Father  f  =   new  Son();  //父类引用指向子类对象

 显然,这样就可以了。需要注意,new  Son()表示在在堆中分配了一段空间来存放类Son中的数据,并返回一个Son的对象,并赋值给Father的引用f,即f指向子类的对象,此时,子类的对象并没有定义一个名字。

 也就是说上面的语句等价于:

                           Son  s  =   new  Son();

                            Father  f  =  s;
注:父类不可调用子类新增的方法,即f不可调用s新增的方法。

好啦,子类转父类就是这样简单,接下来该重点看看父类转子类啦。

按理论上分析的话,父类转子类是不可以实现的。因为子类继承于父类,并新增了一些父类并没有的东西,也就是说,子类对象一般都比父类对象包含更多的东西。这样的话,子类如果访问子类新增的内容, 而这些内容父类并没有,所以就会报错。

那Java里面父类到底可不可以转子类呢?

可以!但是需要满足一个前提,即该父类对象已经指向了子类对象。

如:

                      Father  f  =   new  Son();  //父类引用指向子类对象

                      Son   s2  =  (Son)f;  //可以

                      因为当子类强制转换为父类对象时,并没有实际丢失它原有内存空间(比父类多的那些部分)

                      只是暂时不可访问,所以能再转回来。

此外,当该父类是调用子类构造器创建的时候,它也可以转换为子类。

如:

Employee b=new Manager("a",1000,2,1,225);//父类调用子类的构造器 创建了一个父类对象

这个原理其实和上面的情况一样,因为它也是父类引用指向了子类对象,因此也可以进行转换。

 当然,为了防止报ClassCastExcept异常,一般可以在前面加一条判断句 if(father instanceof Son)

                  如:

                        Father  f  =   new  Son();  //父类引用指向子类对象

                        if(father instanceof Son)

                       {

                                 Son   s2  =  (Son)f;

                      }

这样就可以避免出错。

通过上文的了解,大家可能心里已经有了一些理解,最后再提一下对象在继承关系中的改变

对象的赋值是地址标识的传递,即两个对象名共同使用同一段内存地址。在Java中,对父类与子类对象之间的赋值作了如下规定:

1、子类对象名可以赋值给父类对象名;但父类对象名不可以赋值给子类对象名。

即:父类对象名=子类对象名;

2、如果一个父类对象名已经被子类对象名所赋值,那可以将父类对象名经强制转换赋值给子类对象名。

即:子类对象名=(子类类名)父类对象名;

常用的一种形式:方法中形参用父类型,实参用子类的对象名.

总结

对类进行造型转换的应参考以下原则:
1.总是可以“父=子”赋值。此时不需要类型转换。
2.可以执行类型转换“子=(子)父”,但需要运行时进行检查。如果父类变量引用的是正确的子类型,赋值将执行。如果父类变量引用的是不相关的子类型,将会生成class castException异常。
即:如果父类的实例是在子类的实例上塑造的,“子=(子)父”时就不会抛出异常。  
如:
A 是B的父类。
A a= new B(); //父类A的对象a是在子类B的对象上塑造的。
就可以:
B b= (B)a;
3.决不能在不相关的任何类之间执行类的赋值或者类型转换。即类的造型转换仅限于有继承关系的俩个类的对象之间。

好啦,如果大家还是不太明白,可以试一试下面的程序,亲自上手试一试会了解得更透彻一些。

package inheritance;

public class test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
            
        Employee e;
        Manager boss =new Manager("Searchin",52000,2018,10,25);
        Employee[] staff=new Employee[3];
        staff[0]=boss;//子类转父类
        Employee b=new Manager("a",1000,2,1,225);//父类调用子类的构造器 创建了一个父类对象
        //Manager b=new Employee("a",1000,2,1,225);
        Manager a=(Manager)staff[0];//强制类型转换
        System.out.println(staff[0].getName());
        System.out.println(a.getName());
        boss.setBonus(5000);
        //staff[0].setBonus(5000);
        
    }

}


 

package inheritance;

import java.time.*;

public class Employee
{
   private String name;
   private double salary;
   private LocalDate hireDay;

   public Employee(String name, double salary, int year, int month, int day)
   {
      this.name = name;
      this.salary = salary;
      hireDay = LocalDate.of(year, month, day);
   }

   public String getName()
   {
      return name;
   }

   public double getSalary()
   {
      return salary;
   }

   public LocalDate getHireDay()
   {
      return hireDay;
   }

   public void raiseSalary(double byPercent)
   {
      double raise = salary * byPercent / 100;
      salary += raise;
   }
}
package inheritance;

public class Manager extends Employee
{
   private double bonus;


   public Manager(String name, double salary, int year, int month, int day)
   {
      super(name, salary, year, month, day);
      bonus = 0;
   }

   public double getSalary()
   {
      double baseSalary = super.getSalary();
      return baseSalary + bonus;
   }

   public void setBonus(double b)
   {
      bonus = b;
   }
}

猜你喜欢

转载自blog.csdn.net/Searchin_R/article/details/83383525