如何理解父类引用指向子类对象
转载自作者:乔你那熊色
从对象的内存角度来理解试试.
假设现在有一个父类Father,它里面的变量需要占用1M内存.有一个它的子类Son,它里面的变量需要占用0.5M内存.
现在通过代码来看看内存的分配情况:
Father f = new Father();//系统将分配1M内存.
Son s = new Son();//系统将分配1.5M内存!因为子类中有一个隐藏的引用super会指向父类实例,所以在实例化子类之前会先实例化一个父类,也就是说会先执行父类的构造函数.由于s中包含了父类的实例,所以s可以调用父类的方法.
Son s1 = s;//s1指向那1.5M的内存.
Father f1 = (Father)s; 相当于Father f1 = new Son(); 为向上类型转换,可省略,因为子类就是父类,如猫就是动物
//这时f1会指向那1.5M内存中的1M内存,即是说,f1只是指向了s中实例的父类实例对象,所以f1只能调用父类的方法(存储在1M内存中),而不能调用子类的方法(存储在0.5M内存中).
Son s2 = (Son)f; //Error 不可直接向下类型转换
//这句代码运行时会报ClassCastException.因为f中只有1M内存,而子类的引用都必须要有1.5M的内存,所以无法转换.
Son s3 = (Son)f1; 强制类型转换,为向下类型转换,前提是父类引用要先指向子类对象
//这句可以通过运行,这时s3指向那1.5M的内存.由于f1是由s转换过来的,所以它是有1.5M的内存的,只是它指向的只有1M内存.
示例:
1 .如果你想实现多态,那么必须有三个条件,父类引用,子类对象,方法覆盖你这里如果Fathor类有一个show()方法,那么形成方法覆盖,那么此时就可以这么写:obj.show(),此刻形成了多态.
2. 没有方法覆盖,那你这里只能解释为父类引用去访问一个子类的方法,当然,父类引用没有这么大范围的权限,当然会报错 PS:多态实际上是一种机制,在编译时刻,会生成一张虚拟表,来记录所有覆盖的方法,没有被覆盖的方法是不会记录到这张表的.若一个父类引用调用了没有覆盖的子类方法,那么是不符合该表的,那么编译时刻就会报错. 在执行程序的时候,虚拟机会去这张虚拟表中找覆盖的方法,比如引用中实际上存的是一个子类对象引用,那么就会去找子类中的相应的覆盖的方法来执行