目錄介紹
- 01.什么是綁定
- 02.靜態(tài)和動(dòng)態(tài)綁定
- 03.輔助理解jvm圖
- 04.動(dòng)態(tài)綁定編譯原理
- 05.動(dòng)態(tài)綁定運(yùn)行原理
- 06.兩者之間區(qū)分
- 07.多態(tài)的劃分情況
好消息
- 博客筆記大匯總【16年3月到至今】,包括Java基礎(chǔ)及深入知識(shí)點(diǎn)衣盾,Android技術(shù)博客坦弟,Python學(xué)習(xí)筆記等等敢伸,還包括平時(shí)開(kāi)發(fā)中遇到的bug匯總搓译,當(dāng)然也在工作之余收集了大量的面試題撵枢,長(zhǎng)期更新維護(hù)并且修正吠架,持續(xù)完善……開(kāi)源的文件是markdown格式的芙贫!同時(shí)也開(kāi)源了生活博客,從12年起傍药,積累共計(jì)N篇[近100萬(wàn)字磺平,陸續(xù)搬到網(wǎng)上],轉(zhuǎn)載請(qǐng)注明出處拐辽,謝謝拣挪!
- 鏈接地址:https://github.com/yangchong211/YCBlogs
- 如果覺(jué)得好,可以star一下俱诸,謝謝媒吗!當(dāng)然也歡迎提出建議,萬(wàn)事起于忽微乙埃,量變引起質(zhì)變闸英!
01.什么是綁定
- 把一個(gè)方法與其所在的類/對(duì)象 關(guān)聯(lián)起來(lái)叫做方法的綁定。綁定分為靜態(tài)綁定(前期綁定)和動(dòng)態(tài)綁定(后期綁定)介袜。
02.靜態(tài)和動(dòng)態(tài)綁定
- 靜態(tài)綁定(前期綁定)是指:
- 在程序運(yùn)行前就已經(jīng)知道方法是屬于那個(gè)類的甫何,在編譯的時(shí)候就可以連接到類的中,定位到這個(gè)方法遇伞。
- 在Java中辙喂,final、private、static修飾的方法以及構(gòu)造函數(shù)都是靜態(tài)綁定的巍耗,不需程序運(yùn)行秋麸,不需具體的實(shí)例對(duì)象就可以知道這個(gè)方法的具體內(nèi)容。
- 動(dòng)態(tài)綁定(后期綁定)是指:
- 在程序運(yùn)行過(guò)程中炬太,根據(jù)具體的實(shí)例對(duì)象才能具體確定是哪個(gè)方法灸蟆。
- 動(dòng)態(tài)綁定是多態(tài)性得以實(shí)現(xiàn)的重要因素,它通過(guò)方法表來(lái)實(shí)現(xiàn):每個(gè)類被加載到虛擬機(jī)時(shí)亲族,在方法區(qū)保存元數(shù)據(jù)炒考,其中,包括一個(gè)叫做 方法表(method table)的東西霎迫,表中記錄了這個(gè)類定義的方法的指針斋枢,每個(gè)表項(xiàng)指向一個(gè)具體的方法代碼。如果這個(gè)類重寫(xiě)了父類中的某個(gè)方法知给,則對(duì)應(yīng)表項(xiàng)指向新的代碼實(shí)現(xiàn)處瓤帚。從父類繼承來(lái)的方法位于子類定義的方法的前面。
03.輔助理解jvm圖
- image
04.動(dòng)態(tài)綁定編譯原理
- 我們假設(shè) Father ft=new Son(); ft.say(); Son繼承自Father涩赢,重寫(xiě)了say()戈次。
- 編譯:我們知道,向上轉(zhuǎn)型時(shí)谒主,用父類引用執(zhí)行子類對(duì)象,并可以用父類引用調(diào)用子類中重寫(xiě)了的同名方法赃阀。但是不能調(diào)用子類中新增的方法霎肯,為什么呢?
- 因?yàn)樵诖a的編譯階段榛斯,編譯器通過(guò) 聲明對(duì)象的類型(即引用本身的類型) 在方法區(qū)中該類型的方法表中查找匹配的方法(最佳匹配法:參數(shù)類型最接近的被調(diào)用)观游,如果有則編譯通過(guò)。(這里是根據(jù)聲明的對(duì)象類型來(lái)查找的驮俗,所以此處是查找 Father類的方法表懂缕,而Father類方法表中是沒(méi)有子類新增的方法的,所以不能調(diào)用王凑。)
- 編譯階段是確保方法的存在性搪柑,保證程序能順利、安全運(yùn)行索烹。
05.動(dòng)態(tài)綁定運(yùn)行原理
- 運(yùn)行:我們又知道工碾,ft.say()調(diào)用的是Son中的say(),這不就與上面說(shuō)的百姓,查找Father類的方法表的匹配方法矛盾了嗎渊额?不,這里就是動(dòng)態(tài)綁定機(jī)制的真正體現(xiàn)。
- 上面編譯階段在 聲明對(duì)象類型 的方法表中查找方法旬迹,只是為了安全地通過(guò)編譯(也為了檢驗(yàn)方法是否是存在的)火惊。而在實(shí)際運(yùn)行這條語(yǔ)句時(shí),在執(zhí)行 Father ft=new Son(); 這一句時(shí)創(chuàng)建了一個(gè)Son實(shí)例對(duì)象奔垦,然后在 ft.say() 調(diào)用方法時(shí)屹耐,JVM會(huì)把剛才的son對(duì)象壓入操作數(shù)棧,用它來(lái)進(jìn)行調(diào)用宴倍。而用實(shí)例對(duì)象進(jìn)行方法調(diào)用的過(guò)程就是動(dòng)態(tài)綁定:根據(jù)實(shí)例對(duì)象所屬的類型去查找它的方法表张症,找到匹配的方法進(jìn)行調(diào)用。我們知道鸵贬,子類中如果重寫(xiě)了父類的方法俗他,則方法表中同名表項(xiàng)會(huì)指向子類的方法代碼;若無(wú)重寫(xiě)阔逼,則按照父類中的方法表順序保存在子類方法表中兆衅。故此:動(dòng)態(tài)綁定根據(jù)對(duì)象的類型的方法表查找方法是一定會(huì)匹配(因?yàn)榫幾g時(shí)在父類方法表中以及查找并匹配成功了,說(shuō)明方法是存在的嗜浮。這也解釋了為何向上轉(zhuǎn)型時(shí)父類引用不能調(diào)用子類新增的方法:在父類方法表中必須先對(duì)這個(gè)方法的存在性進(jìn)行檢驗(yàn)羡亩,如果在運(yùn)行時(shí)才檢驗(yàn)就容易出危險(xiǎn)——可能子類中也沒(méi)有這個(gè)方法)。
06.兩者之間區(qū)分
- 程序在JVM運(yùn)行過(guò)程中危融,會(huì)把類的類型信息畏铆、static屬性和方法、final常量等元數(shù)據(jù)加載到方法區(qū)吉殃,這些在類被加載時(shí)就已經(jīng)知道辞居,不需對(duì)象的創(chuàng)建就能訪問(wèn)的,就是靜態(tài)綁定的內(nèi)容蛋勺;需要等對(duì)象創(chuàng)建出來(lái)瓦灶,使用時(shí)根據(jù)堆中的實(shí)例對(duì)象的類型才進(jìn)行取用的就是動(dòng)態(tài)綁定的內(nèi)容。
07.多態(tài)的劃分情況
- 所謂多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過(guò)該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定抱完,而是在程序運(yùn)行期間才確定贼陶,即一個(gè)引用變量倒底會(huì)指向哪個(gè)類的實(shí)例對(duì)象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類中實(shí)現(xiàn)的哪個(gè)方法巧娱,必須在由程序運(yùn)行期間才能決定碉怔。
- 要注意,對(duì)于面向?qū)ο蠖越恚鄳B(tài)分為編譯時(shí)多態(tài)和運(yùn)行時(shí)多態(tài)這兩個(gè)內(nèi)容眨层。其中編譯時(shí)多態(tài)是靜態(tài)的,主要是指方法的重載上荡,它是根據(jù)參數(shù)列表的不同來(lái)區(qū)分不同的函數(shù)趴樱,通過(guò)編譯之后會(huì)變成兩個(gè)不同的函數(shù)馒闷。這個(gè)時(shí)候,在編譯時(shí)候已經(jīng)知道要運(yùn)行哪個(gè)函數(shù)了叁征。而運(yùn)行時(shí)多態(tài)(其實(shí)就是動(dòng)態(tài)綁定)是動(dòng)態(tài)的纳账。他是指在執(zhí)行期間(而不是編譯期間)判斷所引用對(duì)象的實(shí)際類型,并且根據(jù)其實(shí)際類型調(diào)用相應(yīng)實(shí)際使用的方法捺疼。我們其實(shí)一般習(xí)慣上所說(shuō)的多態(tài)疏虫,大部分時(shí)候都指的是運(yùn)行時(shí)多態(tài)。在Java中啤呼,有兩種形式可以實(shí)現(xiàn)多態(tài)卧秘,繼承和接口。
- (1)編譯時(shí)多態(tài)
- 是通過(guò)方法重載實(shí)現(xiàn)的官扣。重載翅敌,是指允許存在多個(gè)同名函數(shù),而這些函數(shù)的參數(shù)表不同(或許參數(shù)個(gè)數(shù)不同惕蹄,或許參數(shù)類型不同(就算是在一個(gè)繼承鏈上下的類型蚯涮,也認(rèn)為是不同的),或許兩者都不同)卖陵。其實(shí)嚴(yán)格來(lái)說(shuō)遭顶,重載的概念并不屬于“面向?qū)ο缶幊獭保剌d的實(shí)現(xiàn)是:編譯器根據(jù)函數(shù)不同的參數(shù)表泪蔫,對(duì)同名函數(shù)的名稱做修飾棒旗,然后這些同名函數(shù)就成了不同的函數(shù)(至少對(duì)于編譯器來(lái)說(shuō)是這樣的)。
- (2)運(yùn)行時(shí)多態(tài)
- 是通過(guò)覆蓋(重寫(xiě))實(shí)現(xiàn)的撩荣,也就是override铣揉。覆蓋,是指子類重新定義父類的函數(shù)婿滓。方法覆蓋需要子類方法和父類方法的名稱老速、參數(shù)類型和返回類型都完全一致(其實(shí)返回類型不一定要一致粥喜,子類的方法返回類型比父類縮小也允許)凸主。一般可以在子類的覆蓋的方法前面加上@override來(lái)保證這個(gè)方法確實(shí)是覆蓋。使用父類引用指向子類對(duì)象额湘,再調(diào)用某一父類中的方法時(shí)卿吐,不同子類會(huì)表現(xiàn)出不同結(jié)果。如果通過(guò)一個(gè)父類的引用來(lái)調(diào)用某方法锋华,實(shí)際上他會(huì)對(duì)應(yīng)到內(nèi)存中真正的對(duì)象嗡官,他會(huì)判斷內(nèi)存中真正的對(duì)象是子類對(duì)象還是父類對(duì)象,然后判斷要調(diào)用哪個(gè)方法毯焕。查找順序是先在子類中找衍腥,有就使用磺樱,沒(méi)有就在父類中找,有就使用婆咸,再?zèng)]有就報(bào)錯(cuò)了竹捉。
其他介紹
01.關(guān)于博客匯總鏈接
- 1.技術(shù)博客匯總
- 2.開(kāi)源項(xiàng)目匯總
- 3.生活博客匯總
- 4.喜馬拉雅音頻匯總
- 5.其他匯總
02.關(guān)于我的博客
- 我的個(gè)人站點(diǎn):www.yczbj.org,www.ycbjie.cn
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yczbj/activities
- 簡(jiǎn)書(shū):http://www.reibang.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜馬拉雅聽(tīng)書(shū):http://www.ximalaya.com/zhubo/71989305/
- 開(kāi)源中國(guó):https://my.oschina.net/zbj1618/blog
- 泡在網(wǎng)上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 郵箱:yangchong211@163.com
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault頭條:https://segmentfault.com/u/xiangjianyu/articles
- 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e