java?JVM方法分派模型靜態(tài)分派動(dòng)態(tài)分派全面講解
前言
- 了解 行為方法分派 有利于在行為分派時(shí)時(shí)進(jìn)行一些功能操作
- 本文全面講解行為分派的類型:靜態(tài) & 動(dòng)態(tài)行為分派,希望你們會(huì)喜歡。
目錄結(jié)構(gòu)圖
1. 知識(shí)儲(chǔ)備
1.1 分派
- 定義:確定執(zhí)行哪個(gè)方法 的過(guò)程
a. 疑問(wèn)
有些讀者會(huì)問(wèn),方法的執(zhí)行不是取決于代碼設(shè)置中的執(zhí)行對(duì)象嗎?為什么還要選擇呢?
b. 回答
- 若 一個(gè)對(duì)象對(duì)應(yīng)于多個(gè)方法 時(shí),就需要進(jìn)行選擇了
- 讀者應(yīng)該都想到了
Java
中的特性:多態(tài),即重寫 & 重載。下面我會(huì)詳細(xì)講解。 - 分類:靜態(tài)分派 & 動(dòng)態(tài)分派。下面我將詳細(xì)講解。
1.2 變量的靜態(tài)類型 & 動(dòng)態(tài)類型
先看下面的代碼
public class Test { static abstract class Human { } static class Man extends Human { } static class Woman extends Human { } // 執(zhí)行代碼 public static void main(String[] args) { Human man = new Man(); // 變量man的靜態(tài)類型 = 引用類型 = Human:不會(huì)被改變、在編譯器可知 // 變量man的動(dòng)態(tài)類型 = 實(shí)例對(duì)象類型 = Man:會(huì)變化、在運(yùn)行期才可知 } }
即:
- 變量的靜態(tài)類型 = 引用類型 :不會(huì)被改變、在編譯器可知
- 變量的動(dòng)態(tài)類型 = 實(shí)例對(duì)象類型 :會(huì)變化、在運(yùn)行期才可知
下面,我將詳細(xì)講解Java
中的分派類型:靜態(tài)分派 & 動(dòng)態(tài)分派
2. 靜態(tài)分派
定義: 根據(jù) 變量的靜態(tài)類型 進(jìn)行方法分派 的 行為
- 即根據(jù) 變量的靜態(tài)類型 確定執(zhí)行哪個(gè)方法
- 發(fā)生在編譯期,所以不由
Java
虛擬機(jī)來(lái)執(zhí)行
應(yīng)用場(chǎng)景: 方法重載(OverLoad
)
實(shí)例說(shuō)明
public class Test { // 類定義 static abstract class Human { } // 繼承自抽象類Human static class Man extends Human { } static class Woman extends Human { } // 可供重載的方法 public void sayHello(Human guy) { System.out.println("hello,guy!"); } public void sayHello(Man guy) { System.out.println("hello gentleman!"); } public void sayHello(Woman guy) { System.out.println("hello lady!"); } // 測(cè)試代碼 public static void main(String[] args) { Human man = new Man(); Human woman = new Woman(); Test test = new Test(); test.sayHello(man); test.sayHello(woman); } } // 運(yùn)行結(jié)果 hello,guy! hello,guy!
根據(jù)上述的講解,大家應(yīng)該明白運(yùn)行結(jié)果的原因:
- 方法重載(
OverLoad
) = 靜態(tài)分派 = 根據(jù) 變量的靜態(tài)類型 確定執(zhí)行(重載)哪個(gè)方法 - 所以上述的方法執(zhí)行時(shí),是根據(jù)變量(
man
、woman
)的靜態(tài)類型(Human
)確定重載sayHello()
中參數(shù)為Human guy
的方法,即sayHello(Human guy)
特別注意
a. 變量的靜態(tài)類型 發(fā)生變化 的情況
可通過(guò) 強(qiáng)制類型轉(zhuǎn)換 改變 變量的靜態(tài)類型
Human man = new Man(); test.sayHello((Man)man); // 強(qiáng)制類型轉(zhuǎn)換 // 此時(shí)man的靜態(tài)類型從 Human 變?yōu)?Man // 所以會(huì)調(diào)用sayHello()中參數(shù)為Man guy的方法,即sayHello(Man guy)
b. 靜態(tài)分派的優(yōu)先級(jí)匹配問(wèn)題
問(wèn)題描述:
- 背景 現(xiàn)需要進(jìn)行靜態(tài)分派
- 問(wèn)題 程序中 沒(méi)有顯示指定 靜態(tài)類型
- 解決方案 程序會(huì)根據(jù) 靜態(tài)類型的優(yōu)先級(jí) 從而選擇 優(yōu)先的靜態(tài)類型進(jìn)行方法分配。
實(shí)例說(shuō)明
public class Overload { private static void sayHello(char arg){ System.out.println("hello char"); } private static void sayHello(Object arg){ System.out.println("hello Object"); } private static void sayHello(int arg){ System.out.println("hello int"); } private static void sayHello(long arg){ System.out.println("hello long"); } // 測(cè)試代碼 public static void main(String[] args) { sayHello('a'); } } // 運(yùn)行結(jié)果 hello char
因?yàn)?code>‘a’是一個(gè)char
類型數(shù)據(jù)(即靜態(tài)類型是char
),所以會(huì)選擇參數(shù)類型為char
的重載方法。
若注釋掉sayHello(char arg)
方法,那么會(huì)輸出
hello int
因?yàn)?code>‘a’除了可代表字符串,還可代表數(shù)字97。因此當(dāng)沒(méi)有最合適的sayHello(char arg)
方式進(jìn)行重載時(shí),會(huì)選擇第二合適(第二優(yōu)先級(jí))的方法重載,即 sayHello(int arg)
總結(jié):當(dāng)沒(méi)有最合適的方法進(jìn)行重載時(shí),會(huì)選優(yōu)先級(jí)第二高的的方法進(jìn)行重載,如此類推。
優(yōu)先級(jí)順序?yàn)椋?/p>
char>int>long>float>double>Character>Serializable>Object>...
其中...
為變長(zhǎng)參數(shù),將其視為一個(gè)數(shù)組元素。變長(zhǎng)參數(shù)的重載優(yōu)先級(jí)最低。
因?yàn)?char
轉(zhuǎn)型到 byte
或 short
的過(guò)程是不安全的,所以不會(huì)選擇參數(shù)類型為byte
或 short
的方法進(jìn)行重載,故優(yōu)先級(jí)列表里也沒(méi)有。
特別注意
- 上面講解的主要是 基本數(shù)據(jù)類型的優(yōu)先級(jí)匹配問(wèn)題
- 若是引用類型,則根據(jù) 繼承關(guān)系 進(jìn)行優(yōu)先級(jí)匹配
注意只跟其編譯時(shí)類型(即靜態(tài)類型)相關(guān)
3. 動(dòng)態(tài)分派
- 定義 根據(jù) 變量的動(dòng)態(tài)類型 進(jìn)行方法分派 的 行為
即根據(jù) 變量的動(dòng)態(tài)類型 確定執(zhí)行哪個(gè)方法
- 應(yīng)用場(chǎng)景 方法重寫(
Override
) - 實(shí)例說(shuō)明
// 定義類 class Human { public void sayHello(){ System.out.println("Human say hello"); } } // 繼承自 抽象類Human 并 重寫sayHello() class Man extends Human { @Override protected void sayHello() { System.out.println("man say hello"); } } class Woman extends Human { @Override protected void sayHello() { System.out.println("woman say hello"); } } // 測(cè)試代碼 public static void main(String[] args) { // 情況1 Human man = new man(); man.sayHello(); // 情況2 man = new Woman(); man.sayHello(); } } // 運(yùn)行結(jié)果 man say hello woman say hello // 原因解析 // 1. 方法重寫(Override) = 動(dòng)態(tài)分派 = 根據(jù) 變量的動(dòng)態(tài)類型 確定執(zhí)行(重寫)哪個(gè)方法 // 2. 對(duì)于情況1:根據(jù)變量(Man)的動(dòng)態(tài)類型(man)確定調(diào)用man中的重寫方法sayHello() // 3. 對(duì)于情況2:根據(jù)變量(Man)的動(dòng)態(tài)類型(woman)確定調(diào)用woman中的重寫方法sayHello()
特別注意
對(duì)于代碼中:
Human man = new Man(); man = new Woman(); man.sayHello(); // man稱為執(zhí)行sayHello()方法的所有者,即接受者。
invokevirtual
指令執(zhí)行的第一步 = 確定接受者的實(shí)際類型invokevirtual
指令執(zhí)行的第二步 = 將 常量池中 類方法符號(hào)引用 解析到不同的直接引用上
第二步即方法重寫(Override
)的本質(zhì)
4. 二者區(qū)別
總結(jié)
本文全面講解方法分派的類型 & 過(guò)程,更多關(guān)于java JVM靜態(tài)動(dòng)態(tài)分派模型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于Sentinel中冷啟動(dòng)限流原理WarmUpController
這篇文章主要介紹了關(guān)于Sentinel中冷啟動(dòng)限流原理WarmUpController,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2023-04-04SpringBoot自定義注解實(shí)現(xiàn)Token校驗(yàn)的方法
這篇文章主要介紹了SpringBoot自定義注解實(shí)現(xiàn)Token校驗(yàn)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03SpringBoot中的PropertySource原理詳解
這篇文章主要介紹了SpringBoot中的PropertySource原理詳解,PropertySource?是一個(gè)非常重要的概念,它允許您在應(yīng)用程序中定義屬性,并將這些屬性注入到?Spring?環(huán)境中,需要的朋友可以參考下2023-07-07Java中在時(shí)間戳計(jì)算的過(guò)程中遇到的數(shù)據(jù)溢出問(wèn)題解決
這篇文章主要介紹了Java中在時(shí)間戳計(jì)算的過(guò)程中遇到的數(shù)據(jù)溢出問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06java統(tǒng)計(jì)字符串中指定元素出現(xiàn)次數(shù)方法
這篇文章主要介紹了java統(tǒng)計(jì)字符串中指定元素出現(xiàn)次數(shù)方法,需要的朋友可以參考下2015-12-12SpringBoot集成支付寶沙箱支付的實(shí)現(xiàn)示例
本文主要介紹了SpringBoot集成支付寶沙箱支付的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12Spring Cloud Alibaba Nacos 入門詳解
這篇文章主要介紹了Spring Cloud Alibaba Nacos入門詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03