子类重新实现父类的方法称重写;重写时可以修改访问权限修饰符和返回值,方法名和参数类型及个数都不可以修改;仅当返回值为类类型时,重写的方法才可以修改返回值类型,且必须是父类方法返回值的子类;要么就不修改,与父类返回值类型相同。那么,该如何理解呢?为什么要是父类返回值类型的子类?
提出问题:子类必须重写父类所有方法吗?
Java,子类不是必须重写父类所有方法的,分为以下两种情况:
父类方法为抽象方法时,子类必须重写(实现)所有父类的抽象方法;
父类方法为普通方法时,子类可以重写父类方法,也可以不重写。
举例如下:
抽象类一个{ 公共空间(){ } 公共抽象空白b (); } 公共B类扩展了{//必须重写b方法,一方法可以不重写 公共空间b () { } }
还是先看示例,详见下文。
包人类中定义了三个类,类,学生类和TestMain类,其学生类中是人类的子类。代码分别如下:
人类的代码如下:
包人; 公共类人{ 字符串名称; int年龄;//测试:重写 公众人物覆盖(){ 人每=new (); per.name=傲酢? 回报; } }
学生类重写了父类的覆盖()方法,代码如下:
包人; 公开课学生扩展人{ 字符串stuNumber; int分数;//测试:重写 公开学生覆盖(){ 学生stu=new (); stu.name="李"; 返回斯图; } }
TestMain类的代码如下:
包人; 公开课TestMain { 公共静态void main (String [] args) { 学生stu=new (); 人每=new (); 每=stu.overRide (); System.out.println (per.name); 每=per.overRide (); System.out.println (per.name); }
输出结果为:
李 李
有没有人跟我一样,第一反应输出应该为“李刘”呢,怎么两个都是“李”?
仔细分析一下,看下面的几张内存图就明白了。
第1,第2条语句分别创建一个子类对象和一个父类对象,其中,斯图指向子类对象,每指向父类对象。如下面图1所示:
接着执行第3条语句:每=stu.overRide ();。
斯图先调用覆盖(),方法体里创建了一个子类对象,并让临时变量stu指向该对象,其存储位置就是以C为首地址的内存块;
然后把该对象的变量名称赋值为“李”;最后返回斯图的值并赋给每一个,也就是说,虽然每是父类对象引用,但最后指向了覆盖()里创建的子类对象,这里以蓝色箭头表示,原先指向的以B为首地址的父类对象这时没有引用指向它,这里把红色箭头变为虚线表示。此时访问每一个的名字,显然是“李”。内存结构见图2:
再接着要执行/=per.overRide();,调用覆盖()方法;
由于子类重写了父类的覆盖()方法,虽然每为父类对象引用,此时父类的该方法被覆盖,所以此时要调用子类的方法;执行过程同上,每不再指向以C为首地址的子类对象,改为指向新创建的子类对象,以D为首地址,如图3所示。
同上面一样的道理,此时访问每个的名字仍然为“李”,因为父类的覆盖()两次压根都没有被调用到。
修改一下TestMain,如下所示:
包人; 公开课TestMain { 公共静态void main (String [] args) { 学生stu=new (); 人每=new (); 人per2=每;///=stu.overRide (); System.out.println (per.name); 每=per.overRide (); System.out.println (per.name); per2=per2.overRide ();//System.out.println (per2.name);//}
此时定义了一个父类对象引用per2,并让它与每指向同一个对象,最后两行,由per2调用覆盖()方法,很显然要调用父类的方法,所以方法体中创建的也是父类的对象,再把结果返回给per2,此时per2指向新创建的父类对象,该父类对象的名字就为“刘”了。