java多態(tài)復(fù)習(xí)

最近在復(fù)習(xí)java基礎(chǔ)瘫寝,在多態(tài)上面有一些不太明白的地方,故記錄下來供自己時(shí)時(shí)復(fù)習(xí)查閱鞏固稠炬。

概述

我們都知道面向?qū)ο笥腥筇匦裕?b>封裝焕阿,繼承,多態(tài)首启。封裝很好理解暮屡,就是對于數(shù)據(jù)的保護(hù)機(jī)制,對外部隱藏內(nèi)部的實(shí)現(xiàn)細(xì)節(jié)毅桃,僅僅暴露訪問方法褒纲,這樣的好處在于對于業(yè)務(wù)來說不用關(guān)心實(shí)現(xiàn)細(xì)節(jié),而當(dāng)實(shí)現(xiàn)細(xì)節(jié)需要改變時(shí)钥飞,也不會影響外部業(yè)務(wù)外厂,可以說,封裝是解耦的基礎(chǔ)代承,也是面向?qū)ο笏枷氲目s影汁蝶。

繼承和多態(tài)往往會把它們放在一起講,繼承是為了重用父類并對父類進(jìn)行擴(kuò)展论悴,正式因?yàn)橛辛死^承掖棉,才導(dǎo)致了多態(tài)的出現(xiàn),那么多態(tài)到底定義是什么呢膀估?所謂多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定幔亥,而是在程序運(yùn)行期間才確定,即一個(gè)引用變量倒底會指向哪個(gè)類的實(shí)例對象察纯,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類中實(shí)現(xiàn)的方法帕棉,必須在由程序運(yùn)行期間才能決定。因?yàn)樵诔绦蜻\(yùn)行時(shí)才確定具體的類饼记,這樣香伴,不用修改源程序代碼,就可以讓引用變量綁定到各種不同的類實(shí)現(xiàn)上具则,從而導(dǎo)致該引用調(diào)用的具體方法隨之改變即纲,即不修改程序代碼就可以改變程序運(yùn)行時(shí)所綁定的具體代碼,讓程序可以選擇多個(gè)運(yùn)行狀態(tài)博肋,這就是多態(tài)性低斋。

什么意思呢蜂厅?比如有一個(gè)汽車類Car,車庫里面有奔馳Benz膊畴、寶馬BMW掘猿、比亞迪BYD,那么可以有如下構(gòu)建方法

Car a = new Benz();

Car b = new BMW();

Car c = new BYD();

我們事前并不知道這輛車是什么車唇跨,只有當(dāng)它開出來我們才能知道术奖,這就是多態(tài)——我們只有在運(yùn)行的時(shí)候才會知道引用變量所指向的具體實(shí)例對象。

向上轉(zhuǎn)型

要理解多態(tài)就要知道什么叫向上轉(zhuǎn)型轻绞,在上述例子中,如果只是像如下創(chuàng)建

Benz a = new Benz();

那就只是一個(gè)單純的實(shí)例化了一個(gè)Benz對象佣耐,但是如果是這樣呢政勃?

Car a = new Benz();

我們可以看到,我們定義了一個(gè)Car的引用兼砖,指向了Benz實(shí)例對象奸远,可以這樣的原因是Benz繼承于Car,所以Benz可以轉(zhuǎn)型為Car讽挟,這個(gè)過程就叫做向上轉(zhuǎn)型懒叛。這樣做存在一個(gè)非常大的好處,在繼承中我們知道子類是父類的擴(kuò)展耽梅,它可以提供比父類更加強(qiáng)大的功能薛窥,如果我們定義了一個(gè)指向子類的父類引用類型,那么它除了能夠引用父類的共性外眼姐,還可以使用子類強(qiáng)大的功能诅迷。

但是向上轉(zhuǎn)型存在一些缺憾,那就是它必定會導(dǎo)致一些方法和屬性的丟失众旗,而導(dǎo)致我們不能夠獲取它們罢杉。所以父類類型的引用可以調(diào)用父類中定義的所有屬性和方法,對于只存在與子類中的方法和屬性無法調(diào)用贡歧。

public class Wine {

? ? public void fun1(){

? ? ? ? System.out.println("Wine 的Fun.....");

? ? ? ? fun2();

? ? }


? ? public void fun2(){

? ? ? ? System.out.println("Wine 的Fun2...");

? ? }

}

public class JNC extends Wine{

? ? /**

? ? * @desc 子類重載父類方法

? ? *? ? ? ? 父類中不存在該方法滩租,向上轉(zhuǎn)型后,父類是不能引用該方法的

? ? * @param a

? ? * @return void

? ? */

? ? public void fun1(String a){

? ? ? ? System.out.println("JNC 的 Fun1...");

? ? ? ? fun2();

? ? }


? ? /**

? ? * 子類重寫父類方法

? ? * 指向子類的父類引用調(diào)用fun2時(shí)利朵,必定是調(diào)用該方法

? ? */

? ? public void fun2(){

? ? ? ? System.out.println("JNC 的Fun2...");

? ? }

}

public class Test {

? ? public static void main(String[] args) {

? ? ? ? Wine a = new JNC();

? ? ? ? a.fun1();

? ? }

}

-------------------------------------------------

Output:

Wine 的Fun.....

JNC 的Fun2...

分析:在這個(gè)程序中子類JNC重載了父類Wine的方法fun1()律想,重寫fun2(),而且重載后的fun1(String a)與 fun1()不是同一個(gè)方法绍弟,由于父類中沒有該方法蜘欲,向上轉(zhuǎn)型后會丟失該方法,所以執(zhí)行JNC的Wine類型引用是不能引用fun1(String a)方法晌柬。而子類JNC重寫了fun2() 姥份,那么指向JNC的Wine引用會調(diào)用JNC中fun2()方法郭脂。

?所以對于多態(tài)我們可以總結(jié)如下:

多態(tài)的必要條件有3個(gè),繼承澈歉,重寫展鸡,向上轉(zhuǎn)型。指向子類的父類引用由于向上轉(zhuǎn)型了埃难,它只能訪問父類中擁有的方法和屬性莹弊,而對于子類中存在而父類中不存在的方法,該引用是不能使用的涡尘,盡管是重載該方法忍弛。若子類重寫了父類中的某些方法,在調(diào)用該些方法的時(shí)候考抄,必定是使用子類中定義的這些方法(動態(tài)連接细疚、動態(tài)調(diào)用)。

再看一個(gè)經(jīng)典例子

public class A {

? ? public String show(D obj) {

? ? ? ? return ("A and D");

? ? }

? ? public String show(A obj) {

? ? ? ? return ("A and A");

? ? }

}

public class B extends A{

? ? public String show(B obj){

? ? ? ? return ("B and B");

? ? }


? ? public String show(A obj){

? ? ? ? return ("B and A");

? ? }

}

public class C extends B{

}

public class D extends B{

}

public class Test {

? ? public static void main(String[] args) {

? ? ? ? A a1 = new A();

? ? ? ? A a2 = new B();

? ? ? ? B b = new B();

? ? ? ? C c = new C();

? ? ? ? D d = new D();


? ? ? ? System.out.println("1--" + a1.show(b));

? ? ? ? System.out.println("2--" + a1.show(c));

? ? ? ? System.out.println("3--" + a1.show(d));

? ? ? ? System.out.println("4--" + a2.show(b));

? ? ? ? System.out.println("5--" + a2.show(c));

? ? ? ? System.out.println("6--" + a2.show(d));

? ? ? ? System.out.println("7--" + b.show(b));

? ? ? ? System.out.println("8--" + b.show(c));

? ? ? ? System.out.println("9--" + b.show(d));? ? ?

? ? }

}

結(jié)果為

1--A and A

2--A and A

3--A and D

4--B and A

5--B and A

6--A and D

7--B and B

8--B and B

9--A and D

分析一下:

1.?a1.show(b)川梅,由于B extends A,所以真正調(diào)用的是A.show(A)

2.a1.show(c)疯兼,由于C extends B,B extends A,所以真正調(diào)用的是A.show(A)

3.a1.show(d)贫途,直接調(diào)用A.show(D)

4.a2.show(b)吧彪,可能這里會疑惑為什么不是B and B,原因在于雖然B繼承了A丢早,但是父類A中其實(shí)是沒有show(B)這個(gè)方法的姨裸,上面有說到,?指向子類的父類引用由于向上轉(zhuǎn)型了怨酝,它只能訪問父類中擁有的方法和屬性啦扬,而對于子類中存在而父類中不存在的方法,該引用是不能使用的凫碌,所以最后是調(diào)用的B類的show(A)方法扑毡,因?yàn)锽繼承A。

5.a2.show(c)盛险,同4理瞄摊。

6.a2.show(d),父類中存在show(D)方法苦掘,而子類B并沒有重寫换帜,所以直接調(diào)用A.show(D)

7.?b.show(b),b是創(chuàng)建的B對象鹤啡,也是B的引用惯驼,不存在向上轉(zhuǎn)型,所以直接調(diào)用B.show(B)

8.b.show(c),父類A中沒有show(C)方法祟牲,所以會調(diào)用子類隙畜,又由于C繼承于B,B繼承于A说贝,在調(diào)用中议惰,會調(diào)用繼承關(guān)系最近的那一個(gè),所以直接調(diào)用B.show(B)

9.b.show(d)乡恕,父類A中有方法show(D)言询,而子類B中并沒有重寫,所以直接調(diào)用A.show(D)

通過上面例子可以發(fā)現(xiàn)一個(gè)事實(shí)傲宜,在繼承鏈中對象方法的調(diào)用存在一個(gè)優(yōu)先級:this.show(O)运杭、super.show(O)、this.show((super)O)函卒、super.show((super)O)辆憔。在例子的5中,a2.show(c)谆趾,a2是A類型的引用變量,所以this就代表了A叛本,a2.show(c),它在A類中找發(fā)現(xiàn)沒有找到沪蓬,于是到A的超類中找(super),由于A沒有超類(Object除外)来候,所以跳到第三級跷叉,也就是this.show((super)O),C的超類有B营搅、A云挟,所以(super)O為B、A转质,this同樣是A园欣,這里在A中找到了show(A obj),同時(shí)由于a2是B類的一個(gè)引用且B類重寫了show(A obj)休蟹,因此最終會調(diào)用子類B類的show(A obj)方法沸枯,結(jié)果也就是B and A。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赂弓,一起剝皮案震驚了整個(gè)濱河市绑榴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌盈魁,老刑警劉巖翔怎,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡赤套,警方通過查閱死者的電腦和手機(jī)飘痛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來于毙,“玉大人敦冬,你說我怎么就攤上這事∥ň冢” “怎么了脖旱?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長介蛉。 經(jīng)常有香客問我萌庆,道長,這世上最難降的妖魔是什么币旧? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任践险,我火速辦了婚禮,結(jié)果婚禮上吹菱,老公的妹妹穿的比我還像新娘巍虫。我一直安慰自己,他們只是感情好鳍刷,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布占遥。 她就那樣靜靜地躺著,像睡著了一般输瓜。 火紅的嫁衣襯著肌膚如雪瓦胎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天尤揣,我揣著相機(jī)與錄音搔啊,去河邊找鬼。 笑死北戏,一個(gè)胖子當(dāng)著我的面吹牛负芋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嗜愈,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼示罗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了芝硬?” 一聲冷哼從身側(cè)響起蚜点,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拌阴,沒想到半個(gè)月后绍绘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年陪拘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厂镇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出识樱,到底是詐尸還是另有隱情君仆,我是刑警寧澤惦辛,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏掌挚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一菩咨、第九天 我趴在偏房一處隱蔽的房頂上張望吠式。 院中可真熱鬧,春花似錦抽米、人聲如沸特占。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽是目。三九已至,卻和暖如春查辩,著一層夾襖步出監(jiān)牢的瞬間胖笛,已是汗流浹背网持。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工宜岛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人功舀。 一個(gè)月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓萍倡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辟汰。 傳聞我的和親對象是個(gè)殘疾皇子列敲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法帖汞,內(nèi)部類的語法戴而,繼承相關(guān)的語法,異常的語法翩蘸,線程的語...
    子非魚_t_閱讀 31,587評論 18 399
  • 一:java概述: 1所意,JDK:Java Development Kit,java的開發(fā)和運(yùn)行環(huán)境,java的開發(fā)...
    慕容小偉閱讀 1,766評論 0 10
  • Win7下如何打開DOS控制臺扶踊? a:開始--所有程序--附件--命令提示符 b:開始--搜索程序和文件--cmd...
    逍遙嘆6閱讀 1,588評論 4 12
  • 我是一名新入門的學(xué)生泄鹏,用Android studio運(yùn)行一個(gè)自己編譯的app可是運(yùn)行不起來,有誰幫幫我嘛秧耗?拜托拜托
    扎心的默兒閱讀 161評論 0 0
  • 生活不止眼前的茍且备籽,還有詩和遠(yuǎn)方的田野 。 距離寫生回來已經(jīng)快一個(gè)月了分井,突然想著寫點(diǎn)兒東西來紀(jì)念此行车猬。不...
    獨(dú)孤云逸閱讀 1,005評論 7 17