Java編程關(guān)于子類(lèi)重寫(xiě)父類(lèi)方法問(wèn)題的理解
子類(lèi)重新實(shí)現(xiàn)父類(lèi)的方法稱(chēng)重寫(xiě);重寫(xiě)時(shí)可以修改訪(fǎng)問(wèn)權(quán)限修飾符和返回值,方法名和參數(shù)類(lèi)型及個(gè)數(shù)都不可以修改;僅當(dāng)返回值為類(lèi)類(lèi)型時(shí),重寫(xiě)的方法才可以修改返回值類(lèi)型,且必須是父類(lèi)方法返回值的子類(lèi);要么就不修改,與父類(lèi)返回值類(lèi)型相同。那么,該如何理解呢?為什么要是父類(lèi)返回值類(lèi)型的子類(lèi)?
提出問(wèn)題:子類(lèi)必須重寫(xiě)父類(lèi)所有方法嗎?
Java,子類(lèi)不是必須重寫(xiě)父類(lèi)所有方法的,分為以下兩種情況:
父類(lèi)方法為抽象方法時(shí),子類(lèi)必須重寫(xiě)(實(shí)現(xiàn))所有父類(lèi)的抽象方法;
父類(lèi)方法為普通方法時(shí),子類(lèi)可以重寫(xiě)父類(lèi)方法,也可以不重寫(xiě)。
舉例如下:
abstract class A{ public void a(){ } public abstract void b(); } public class B extends A{ //必須重寫(xiě)b方法,a方法可以不重寫(xiě) public void b(){ } }
還是先看示例,詳見(jiàn)下文。
包human中定義了三個(gè)類(lèi),Person類(lèi)、Student類(lèi)和TestMain類(lèi),其中Student類(lèi)是Person類(lèi)的子類(lèi)。代碼分別如下:
Person類(lèi)的代碼如下:
package human; public class Person { String name; int age; //test:重寫(xiě) public Person overRide() { Person per = new Person(); per.name = "liu"; return per; } }
Student類(lèi)重寫(xiě)了父類(lèi)的overRide()方法,代碼如下:
package human; public class Student extends Person { String stuNumber; int score; //test:重寫(xiě) public Student overRide() { Student stu = new Student(); stu.name = "li"; return stu; } }
TestMain類(lèi)的代碼如下:
package human; public class TestMain { public static void main(String[] args) { Student stu = new Student(); Person per = new Person(); per = stu.overRide(); System.out.println(per.name); per = per.overRide(); System.out.println(per.name); }
輸出結(jié)果為:
li li
有沒(méi)有人跟我一樣,第一反應(yīng)輸出應(yīng)該為“l(fā)i liu”呢,怎么兩個(gè)都是“l(fā)i”?
仔細(xì)分析一下,看下面的幾張內(nèi)存圖就明白了。
第1、第2條語(yǔ)句分別創(chuàng)建一個(gè)子類(lèi)對(duì)象和一個(gè)父類(lèi)對(duì)象,其中,stu指向子類(lèi)對(duì)象,per指向父類(lèi)對(duì)象。如下面圖1所示:
接著執(zhí)行第3條語(yǔ)句:per = stu.overRide();;
stu先調(diào)用overRide(),方法體里創(chuàng)建了一個(gè)子類(lèi)對(duì)象,并讓臨時(shí)變量stu指向該對(duì)象,其存儲(chǔ)位置就是以C為首地址的內(nèi)存塊;
然后把該對(duì)象的變量name賦值為“l(fā)i”;最后返回stu的值并賦給per,也就是說(shuō),雖然per是父類(lèi)對(duì)象引用,但最后指向了overRide()里創(chuàng)建的子類(lèi)對(duì)象,這里以藍(lán)色箭頭表示; 原先指向的以B為首地址的父類(lèi)對(duì)象這時(shí)沒(méi)有引用指向它,這里把紅色箭頭變?yōu)樘摼€(xiàn)表示。此時(shí)訪(fǎng)問(wèn)per的name,顯然是“l(fā)i”。內(nèi)存結(jié)構(gòu)見(jiàn)圖2:
再接著要執(zhí)行per = per.overRide();,調(diào)用overRide()方法;
由于子類(lèi)重寫(xiě)了父類(lèi)的overRide()方法,雖然per為父類(lèi)對(duì)象引用,此時(shí)父類(lèi)的該方法被覆蓋,所以此時(shí)要調(diào)用子類(lèi)的方法;執(zhí)行過(guò)程同上,per不再指向以C為首地址的子類(lèi)對(duì)象,改為指向新創(chuàng)建的子類(lèi)對(duì)象,以D為首地址,如圖3所示。
同上面一樣的道理,此時(shí)訪(fǎng)問(wèn)per的name仍然為“l(fā)i”,因?yàn)楦割?lèi)的overRide()兩次壓根都沒(méi)有被調(diào)用到。
修改一下TestMain,如下所示:
package human; public class TestMain { public static void main(String[] args) { Student stu = new Student(); Person per = new Person(); Person per2 = per; // per = stu.overRide(); System.out.println(per.name); per = per.overRide(); System.out.println(per.name); per2 = per2.overRide(); // System.out.println(per2.name); // }
此時(shí)定義了一個(gè)父類(lèi)對(duì)象引用per2,并讓它與per指向同一個(gè)對(duì)象;最后兩行,由per2調(diào)用overRide()方法,很顯然要調(diào)用父類(lèi)的方法,所以方法體中創(chuàng)建的也是父類(lèi)的對(duì)象,再把結(jié)果返回給per2,此時(shí)per2指向新創(chuàng)建的父類(lèi)對(duì)象,該父類(lèi)對(duì)象的name就為“l(fā)iu”了。
說(shuō)了這么多,貌似還沒(méi)解決開(kāi)頭的問(wèn)題,為什么是父類(lèi)返回值類(lèi)型的子類(lèi)?為方便說(shuō)明,記父類(lèi)的返回值類(lèi)型為A。
我的理解是,這是為了向上轉(zhuǎn)型;既然子類(lèi)重寫(xiě)了父類(lèi)的方法,有時(shí)候就需要用父類(lèi)對(duì)象引用來(lái)調(diào)用子類(lèi)重寫(xiě)的方法,在上面例子的情況下,也就是說(shuō)要把A的子類(lèi)對(duì)象引用賦給A的對(duì)象引用,如果此時(shí)返回值類(lèi)型不是A類(lèi)或A的子類(lèi),其他類(lèi)的對(duì)象引用是不能賦給A的對(duì)象引用的,這樣就會(huì)出錯(cuò);所以說(shuō),子類(lèi)重寫(xiě)的方法,如果返回值為類(lèi)類(lèi)型,其返回值類(lèi)型必須與父類(lèi)返回值類(lèi)型相同或?yàn)楦割?lèi)返回值類(lèi)型的子類(lèi)。
不知道有沒(méi)有說(shuō)清楚。
PS:例子選得不是特別好,如果返回值類(lèi)型是與Person和Student不相干的類(lèi),可能更好理解,不然容易把返回值的類(lèi)與方法所屬的類(lèi)混淆。
總結(jié)
以上就是本文關(guān)于Java編程關(guān)于子類(lèi)重寫(xiě)父類(lèi)方法問(wèn)題的理解的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:
Java中的靜態(tài)內(nèi)部類(lèi)詳解及代碼示例
Java源碼解析之object類(lèi)
Java AtomicInteger類(lèi)的使用方法詳解
如有不足之處,歡迎留言指出。
上一篇:Java編程實(shí)現(xiàn)swing圓形按鈕實(shí)例代碼
欄 目:Java編程
下一篇:Java編程實(shí)現(xiàn)A*算法完整代碼
本文標(biāo)題:Java編程關(guān)于子類(lèi)重寫(xiě)父類(lèi)方法問(wèn)題的理解
本文地址:http://mengdiqiu.com.cn/a1/Javabiancheng/8405.html
您可能感興趣的文章
- 01-10Java咖啡館(1)——嘆咖啡
- 01-10Java Socket編程(三) 服務(wù)器Sockets
- 01-10Java進(jìn)階:Struts多模塊的技巧
- 01-10Java Socket編程(一) Socket傳輸模式
- 01-10Java Socket編程(二) Java面向連接的類(lèi)
- 01-10Java運(yùn)行時(shí)多態(tài)性的實(shí)現(xiàn)
- 01-10Java經(jīng)驗(yàn)點(diǎn)滴:處理沒(méi)有被捕獲的異常
- 01-10Java Socket編程(四) 重復(fù)和并發(fā)服務(wù)器
- 01-10Java中的浮點(diǎn)數(shù)分析
- 01-10面向?qū)ο缶幊?Java中的抽象數(shù)據(jù)類(lèi)型


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10Java咖啡館(1)——嘆咖啡
- 01-10JVM的垃圾回收機(jī)制詳解和調(diào)優(yōu)
- 01-10Java Socket編程(三) 服務(wù)器Sockets
- 01-10Java進(jìn)階:Struts多模塊的技巧
- 01-10J2SE 1.5版本的新特性一覽
- 01-10Java Socket編程(一) Socket傳輸模式
- 01-10Java運(yùn)行時(shí)多態(tài)性的實(shí)現(xiàn)
- 01-10Java Socket編程(二) Java面向連接的類(lèi)
- 01-10Java Socket編程(四) 重復(fù)和并發(fā)服務(wù)
- 01-10Java經(jīng)驗(yàn)點(diǎn)滴:處理沒(méi)有被捕獲的異常
隨機(jī)閱讀
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10delphi制作wav文件的方法
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-10C#中split用法實(shí)例總結(jié)