方法的重載與重寫(xiě)
重載:同一個(gè)類中出現(xiàn)多個(gè)名字相同昌简,并且參數(shù)類型不同的方法,這些方法之間的關(guān)系侵蒙,稱之為方法重載。
小知識(shí)點(diǎn):這個(gè)限制可以通過(guò)字節(jié)碼工具繞開(kāi)傅蹂。也就是說(shuō)纷闺,在編譯完成之后,我們可以再向 class 文件中添加方法名和參數(shù)類型相同份蝴,而返回類型不同的方法犁功。當(dāng)這種包括多個(gè)方法名相同、參數(shù)類型相同婚夫,而返回類型不同的方法的類浸卦,出現(xiàn)在 Java 編譯器的用戶類路徑上時(shí),它是怎么確定需要調(diào)用哪個(gè)方法的呢案糙?當(dāng)前版本的 Java 編譯器會(huì)直接選取第一個(gè)方法名以及參數(shù)類型匹配的方法限嫌。并且靴庆,它會(huì)根據(jù)所選取方法的返回類型來(lái)決定可不可以通過(guò)編譯,以及需不需要進(jìn)行值轉(zhuǎn)換等萤皂。
重載方法的選取過(guò)程撒穷,重載方法在編譯過(guò)程中即可完成始別●晌酰可以具體到每一個(gè)方法調(diào)用端礼,Java編譯器會(huì)根據(jù)所傳入?yún)?shù)的聲明類型(注意與實(shí)際類型區(qū)分)來(lái)選取重載方法。選取過(guò)程分為三個(gè)階段:
1入录、在不考慮對(duì)基本類型自動(dòng)裝拆箱(auto-boxing蛤奥,auto-unboxing),以及可變長(zhǎng)參數(shù)的情況選取重載方法僚稿;
2凡桥、如果在第一個(gè)階段中沒(méi)有找到適配的方法,那么在允許自動(dòng)裝拆箱蚀同,但不允許可變長(zhǎng)參數(shù)的情況下選取重載方法缅刽;
3、如果在第2個(gè)階段中沒(méi)有找到適配的方法蠢络,那么在允許自動(dòng)裝拆箱以及可變長(zhǎng)參數(shù)的情況下選取重載方法衰猛。
注意:如果Java編譯器在同一個(gè)階段找到了多個(gè)適配的方法,那么它會(huì)在其中選擇一個(gè)最為貼切的刹孔,而決定貼切程度的一個(gè)關(guān)鍵就是形式參數(shù)類型的繼承關(guān)系啡省。
重寫(xiě):如果子類定義與父類中非私有方法、非靜態(tài)方法同名的方法髓霞,而且這兩個(gè)方法的參數(shù)類型相同卦睹,那么這兩個(gè)方法稱之為方法重寫(xiě)。
Java是一門(mén)面向?qū)ο蟮木幊陶Z(yǔ)言方库,它的一個(gè)重要特性便是多態(tài)结序,而方法重寫(xiě),正是多態(tài)最重要的一種體現(xiàn)方式:它允許子類在繼承父類部分功能的同時(shí)纵潦,擁有自己獨(dú)特的行為笼痹。
比如,如果你經(jīng)常漫游酪穿,那么你可能知道,撥打10086會(huì)根據(jù)你當(dāng)前所在地晴裹,連接到當(dāng)?shù)氐目头患谩V貙?xiě)調(diào)用也是如此:他會(huì)根據(jù)調(diào)用者的動(dòng)態(tài)類型,來(lái)選取實(shí)際的目標(biāo)方法涧团。
JVM的靜態(tài)綁定和動(dòng)態(tài)綁定
Java虛擬機(jī)是怎么識(shí)別方法的只磷?
Java虛擬機(jī)識(shí)別方法的關(guān)鍵在于類名经磅、方法名以及方法描述符(method descriptor)。方法描述符钮追,他是由方法的參數(shù)類型以及返回類型所構(gòu)成预厌。在同一個(gè)類中,如果同時(shí)出現(xiàn)多個(gè)名字相同且描述符也相同的方法元媚,那么Java虛擬機(jī)會(huì)在類的驗(yàn)證階段報(bào)錯(cuò)轧叽。
Java虛擬機(jī)與Java語(yǔ)言不同,它并不限制名字與參數(shù)類型相同刊棕,但返回類型不同的方法出現(xiàn)在同一個(gè)類中炭晒,對(duì)于調(diào)用這些方法的字節(jié)碼來(lái)說(shuō),由于字節(jié)碼所附帶的方法描述符包含了返回類型甥角,因此Java虛擬機(jī)能夠準(zhǔn)確地識(shí)別目標(biāo)方法网严。
Java虛擬機(jī)中關(guān)于方法重寫(xiě)的判定同樣基于方法描述符。也就是說(shuō)嗤无,如果子類定義了與父類中非私有震束、非靜態(tài)方法同名的方法,那么只有當(dāng)這兩個(gè)方法的參數(shù)類型以及返回類型一致当犯,Java虛擬機(jī)才會(huì)判定為重寫(xiě)垢村。
對(duì)于Java語(yǔ)言中重寫(xiě)而Java虛擬機(jī)中非重寫(xiě)的情況,編譯器會(huì)通過(guò)生成橋接方法來(lái)實(shí)現(xiàn)Java中的重寫(xiě)語(yǔ)義灶壶。
Java虛擬機(jī)中靜態(tài)綁定指的是在解析時(shí)便能夠直接識(shí)別目標(biāo)方法的情況肝断,而動(dòng)態(tài)綁定則指的是需要在運(yùn)行過(guò)程中根據(jù)調(diào)用者的動(dòng)態(tài)類型來(lái)識(shí)別目標(biāo)方法的情況。
總的來(lái)說(shuō)驰凛,Java字節(jié)碼中與調(diào)用相關(guān)的指令共有五種胸懈。
1、invokestatic:用于調(diào)用靜態(tài)方法恰响。
2趣钱、invokespecial:用于調(diào)用私有實(shí)例方法、構(gòu)造器胚宦,以及使用super關(guān)鍵字調(diào)用父類的實(shí)例方法或構(gòu)造器首有,和所實(shí)現(xiàn)接口的默認(rèn)方法
3、invokevirtual:用于調(diào)用非私有實(shí)例方法枢劝。
4井联、invokeinterface:用于調(diào)用接口方法。
5您旁、invokedynamic:用于調(diào)用動(dòng)態(tài)方法烙常。
出處:《極客時(shí)間》 鄭雨迪老師的《深入拆解Java虛擬機(jī)》
備注:純屬督促自己復(fù)習(xí),梳理每節(jié)知識(shí)點(diǎn)鹤盒。如有錯(cuò)誤蚕脏,請(qǐng)多加指出侦副。謝謝