JVM 方法調(diào)用之靜態(tài)分派(詳解)
分派(Dispatch)可能是靜態(tài)也可能是動(dòng)態(tài)的,根據(jù)分派依據(jù)的宗量數(shù)可分為單分派和多分派。這兩種分派方式的兩兩組合就構(gòu)成了靜態(tài)單分派,靜態(tài)多分派,動(dòng)態(tài)單分派,動(dòng)態(tài)多分派這4種組合。本章講靜態(tài)分派。
1、靜態(tài)分派
所有依賴靜態(tài)類型來定位方法執(zhí)行版本的分派動(dòng)作稱為靜態(tài)分派。靜態(tài)分派的典型應(yīng)用是方法重載。靜態(tài)分派發(fā)生在編譯階段,因此確定靜態(tài)分派的動(dòng)作實(shí)際上不是由虛擬機(jī)來執(zhí)行的。
那么什么是靜態(tài)類型(static type)呢?
Super object = new Sub();
像上面的語句,Super是變量的靜態(tài)類型,Sub是變量的實(shí)際類型(actual type),靜態(tài)類型和實(shí)際類型在程序中都可以發(fā)生一些變化,區(qū)別是靜態(tài)類型的變化僅僅在使用時(shí)發(fā)生,變量本身的靜態(tài)類型不會(huì)被改變,并且最終的靜態(tài)類型是在編譯期可知的;而實(shí)際類型變化 的結(jié)果在運(yùn)行期才可確定,編譯器在編譯程序的時(shí)候并不知道一個(gè)對(duì)象的實(shí)際地址是什么。
靜態(tài)分派一詞實(shí)際上是中文翻譯特有的,國(guó)外的技術(shù)文檔都是將其稱為Method Overload Resolution。這樣一來就更好理解了,因?yàn)槭荝esolution(解析)
下面的代碼可以說明這一點(diǎn):
public static class Printer {
public static void print(Super object) {
System.out.println("it is Super");
}
public static void print(Sub object) {
System.out.println("it is Sub");
}
}
當(dāng)調(diào)用print方法時(shí),打印的將是"it is Super".
2、 調(diào)用“合適”的方法
編譯器雖然能確定出方法的重載版本,但在很多情況下這個(gè)重載版本并不是“唯一的”,往往只能確定一個(gè)“更加合適”的版本。什么意思呢?看看下面的代碼。
public static void main(String[] args) {
char c = 'a';
Printer.print(c);
}
public static class Printer {
public static void print(int i) {
System.out.println("it is int");
}
public static void print(byte b) {
System.out.println("it is byte");
}
}
上面的代碼可以執(zhí)行嗎?乍看之下,沒有類型為char的重載方法,是不是會(huì)報(bào)錯(cuò)?實(shí)際上,會(huì)打印出 it is int。也就是說,雖然沒有char類型參數(shù)的方法,但編譯器通過參數(shù)自動(dòng)轉(zhuǎn)型幫你找到了一個(gè)“合適”的方法調(diào)用。
轉(zhuǎn)換的路徑是char->int->long->float->double,如果還沒找到合適的方法,則自動(dòng)裝箱成Character,此時(shí)已經(jīng)是一個(gè)類。如果還找不到,則開始查找該類實(shí)現(xiàn)的接口(優(yōu)先),父類(在繼承關(guān)系中從下往上找,越接近上層的優(yōu)先級(jí)越低)。如果有多個(gè)接口同時(shí)出現(xiàn)兩個(gè)參數(shù)一致的,此時(shí)優(yōu)先級(jí)是一樣的,編譯器無法確定自動(dòng)轉(zhuǎn)型為哪種類型,會(huì)提示類型模糊,拒絕編譯。程序必須在調(diào)用時(shí)顯式地指定字段的靜態(tài)類型。
下面這個(gè)例子,沒有參數(shù)為Sub的方法,按照參數(shù)自動(dòng)轉(zhuǎn)型,查找最合適方法的方式,會(huì)找到Super為參數(shù)方法調(diào)用。
public static void main(String[] args) {
Sub object = new Sub();
Printer.print(object);
}
public static class Printer {
public static void print(Super object) {
System.out.println("it is Super");
}
}
此外還要注意一點(diǎn)是傳入?yún)?shù)為null. 如果重載方法里有兩個(gè)不同的類型的參數(shù),即使兩者沒有繼承關(guān)系,編譯器也會(huì)判斷不了到底調(diào)用哪個(gè)。
public static void main(String[] args) {
Printer.print(null);
}
public static class Printer {
public static void print(Super object) {
System.out.println("it is Super");
}
public static void print(App app) {
System.out.println("it is App");
}
}

在調(diào)用的時(shí)候強(qiáng)制轉(zhuǎn)換,指定類型,就可以解決了。
Printer.print((App)null);
要注意的一點(diǎn)是,解析與分派這兩者之間的關(guān)系并不是二選一的排他關(guān)系,它們是在不同層次上去篩選,確定目標(biāo)方法的過程。例如,靜態(tài)方法在類加載期就會(huì)解析,但靜態(tài)方法也是可以有重載版本的,選擇重載版本的過程也是通過靜態(tài)分派完成的。
以上這篇JVM 方法調(diào)用之靜態(tài)分派(詳解)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java中l(wèi)ist使用時(shí)需避免的場(chǎng)景總結(jié)
眾所周知,Java為開發(fā)者提供了多種集合類的實(shí)現(xiàn),其中幾乎所有業(yè)務(wù)代碼都需要用到List,但List的錯(cuò)誤使用也會(huì)導(dǎo)致諸多問題,所以本文我們就來看一看幾個(gè)錯(cuò)誤使用List的場(chǎng)景吧2023-10-10
js中去除字符串中所有的html標(biāo)簽代碼實(shí)例
這篇文章主要介紹了js中去除字符串中所有的html標(biāo)簽代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
Java線程中synchronized和volatile關(guān)鍵字的區(qū)別詳解
這篇文章主要介紹了Java線程中synchronized和volatile關(guān)鍵字的區(qū)別詳解,synchronzied既能夠保障可見性,又能保證原子性,而volatile只能保證可見性,無法保證原子性,volatile不需要加鎖,比synchronized更輕量級(jí),不會(huì)阻塞線程,需要的朋友可以參考下2024-01-01
IDEA上運(yùn)行Flink任務(wù)的實(shí)戰(zhàn)教程
這篇文章主要介紹了IDEA上運(yùn)行Flink任務(wù)的實(shí)戰(zhàn)教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
Opencv創(chuàng)建車牌圖片識(shí)別系統(tǒng)方法詳解
本文主要介紹了一個(gè)基于spring?boot+maven+opencv實(shí)現(xiàn)的圖像識(shí)別及訓(xùn)練項(xiàng)目,可以實(shí)現(xiàn)車牌識(shí)別功能,感興趣的可以跟隨小編一起試一試2022-01-01
Java通過MySQL的加解密函數(shù)實(shí)現(xiàn)敏感字段存儲(chǔ)
這篇文章主要介紹了如何在Java中MySQL的加解密函數(shù)實(shí)現(xiàn)敏感字段存儲(chǔ),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-03-03
Java中的關(guān)鍵字_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
關(guān)鍵字也稱為保留字,是指Java語言中規(guī)定了特定含義的標(biāo)示符。對(duì)于保留字,用戶只能按照系統(tǒng)規(guī)定的方式使用,不能自行定義2017-04-04
springboot整合webservice使用簡(jiǎn)單案例總結(jié)
WebService是一個(gè)SOA(面向服務(wù)的編程)的架構(gòu),它是不依賴于語言,平臺(tái)等,可以實(shí)現(xiàn)不同的語言間的相互調(diào)用,下面這篇文章主要給大家介紹了關(guān)于springboot整合webservice使用的相關(guān)資料,需要的朋友可以參考下2024-07-07

