向上转型
我们都知道,狗是动物中的一种,那么如果现在有一个Dog类和Animal类,那么他们的关系就是Dog类继承Animal类。
我们经常说,狗是动物,实际上“狗是动物”这句话就是向上转型的一个例子,即把狗(子类)当做动物(父类)来看待。用一句话来总结,向上转型就是父类的引用指向子类的实例。
实例说明&&内存分析
下面就用一个简单的小例子加上内存分析来理解向上转型。
定义父类Animal和子类Dog
class Animal{ public String name; Animal(String name){ this.name=name; } public void SetName(String name){ this.name=name; } } class Cat extends Animal{ public String furcolor; Cat(String name,String furcolor){ super(name); this.furcolor=furcolor; } public void SetFurcolor(String color){ this.furcolor=color; } }
定义UpCastingTest类
public class UpCastingTest { public static void main(String[] args) { Animal a=new Cat("叮当猫","蓝色"); a.SetName("大脸猫"); System.out.println(a.name); //a.SetFurcolor("黄色"); //System.out.println(a.furcolor); } }
在main方法中虽然定义了Animal类型的变量a,但它指向的是一个Cat类型的实例,如下图:
在上面的内存图中,实例化Dog类时,在堆内存中的Dog类实例中会包含它的父类(即上图中黄色部分),下面的部分是只属于自己的,栈内存中的引用a虽然指向堆内存中的Dog类实例,但它毕竟是一个Animal类型的引用,所以在Dog实例中,除了继承自Animal的那一部分,其余的部分它并看不到。因此我们可以看做a实质上指向的是堆内存中属于Animal类的那一部分(即黄色的那一部分)。所以在main方法中,如果执行注释掉的那两句代码 “a.SetFurcolor("黄色");” 或者 “System.out.println(a.furcolor);” 时就会报错。
因此,当父类的引用指向子类对象的时候,父类的引用只可以访问子类继承于父类的那一部分属性和方法以及子类重写的父类的方法。