如何理解Java向上转型对象的思考
假如student类是people类的子类,我们可以用子类创建一个对象,并把这个对象的引用放到父类中去。比如:
People stu = new Student();
这时我们称对象stu是Student类的对象的上转型对象,上转型对象的实体由子类负责创建,但是对象的模板是根据父类来的。但会失去原子类对象的一些属性和功能,相当于对原子类对象做了简化,上转型对象不能操作子类新增的成员变量和方法(也就是父类没有的)
作用:当一个类有很多子类时,并且这些子类都重写了父类中的某个方法。如果我们把子类创建的对象的引用放到一个父类的对象中时,就得到了这个对象(子类对象)的一个上转型对象,那么这个上转型对象在调用这个方法时可以有很多形态,因为不同子类在重写父类方法时可能产生不同的行为,比如狗的上转型对象调用“叫声”方法时产生的行为是“汪汪汪”,猫类的上转型对象是”喵喵喵“。
啊经过一段时间的理解我差不多悟了一点:其实父类就相当于子类的子集!,当我们new一个子类对象时,子类中有一个隐藏的引用super会指向父类实例,所以在实例化子类之前会先实例化一个父类。所以说子类是包含父类的:在内存中,给子类分配的内存不仅子类本身所需的,还有父类实例对象的内存(比如子类对象本身的数据需要1M内存,父类本身需要2M内存,但创建子类对象时实际分配的内存是3M!因为实例化子类之前要先实例化父类)
People stu = new Student();
我们回到这段代码,对象stu包含了父类people的内存和子类Student的内存,因为创建的的是子类对象,但是由于stu对象前面有People类型修饰它,相当于stu对象的引用(就是地址)指向Student实例对象中的People对象,二者是包含关系,所以这也解释了为何stu对象无法调用子类新增的方法(也就是父类没有的)。
这就是向上转型!我们创建的是一个子类对象,同时子类内存中包含父类,那我们可以把子类对象能调用的范围框起来,限定在父类对象拥有的当中,怎么限定?把子类对象前面的类型修饰符换成父类的。
就是原本代码:
Student stu=new Student();
stu对象前面的修饰符是Student,并且前面说过子类包含父类,所以这时候stu对象既可以访问父类有可以访问子类。
但如果我们把类型修饰符换成People:people stu=new Student()
,那么stu对象的访问范围就被框在People对象中,只能访问People类所拥有的,而无法访问Student子类的。
这也是为什么向上转型往往不会出错(从子类大内存中框定范围变成小内存),而向下转型(由父类转到子类,从父类小内存拓展至子类的大内存)往往会出错,除非是已经向上转型过的再向下转型转回来(就是取消访问限制恢复原状)。
补充知识可能助于理解:对象的引用(地址)是保存在栈中的,实例化对象是保存在堆中的。实例化对象会在堆中分配内存。栈中的对象引用指向堆中分配的内存。
本人Java初学者,写这篇文章的初衷是记录自己的想法,肯定有说的不对的地方。如果您发现了错误欢迎指正,谢谢。