怎么使用java?JVM方法分派模型

蝸牛 互聯網技術資訊 2022-06-24 18 0

這篇文章主要介紹了怎么使用java?JVM方法分派模型的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇怎么使用java?JVM方法分派模型文章都會有所收獲,下面我們一起來看看吧。

1. 知識儲備

1.1 分派

  • 定義:確定執行哪個方法 的過程

a. 疑問 有些讀者會問,方法的執行不是取決于代碼設置中的執行對象嗎?為什么還要選擇呢? b. 回答

  • 若 一個對象對應于多個方法 時,就需要進行選擇了

  • 讀者應該都想到了 Java中的特性:多態,即重寫 & 重載。下面我會詳細講解。

  • 分類:靜態分派 & 動態分派。下面我將詳細講解。

1.2 變量的靜態類型 & 動態類型

先看下面的代碼

public?class?Test?{?
????static?abstract?class?Human?{?
????}?
????static?class?Man?extends?Human?{?
????}?
????static?class?Woman?extends?Human?{?
????}?
//?執行代碼
public?static?void?main(String[]?args)?{?
??Human?man?=?new?Man();?
??//?變量man的靜態類型?=?引用類型?=?Human:不會被改變、在編譯器可知
??//?變量man的動態類型?=?實例對象類型?=?Man:會變化、在運行期才可知
????}?
}

即:

  • 變量的靜態類型 = 引用類型 :不會被改變、在編譯器可知

  • 變量的動態類型 = 實例對象類型 :會變化、在運行期才可知

下面,我將詳細講解Java中的分派類型:靜態分派 & 動態分派

2. 靜態分派

  • 定義 根據 變量的靜態類型 進行方法分派 的 行為

  • 即根據 變量的靜態類型 確定執行哪個方法

  • 發生在編譯期,所以不由 Java 虛擬機來執行

  • 應用場景 方法重載(OverLoad

  • 實例說明

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!");?
????}?
//?測試代碼
????public?static?void?main(String[]?args)?{?
????????Human?man?=?new?Man();?
????????Human?woman?=?new?Woman();?
????????Test?test?=?new?Test();?
????????test.sayHello(man);?
????????test.sayHello(woman);?
????}?
}
//?運行結果
hello,guy!?
hello,guy!

根據上述的講解,大家應該明白運行結果的原因:

  • 方法重載(OverLoad) = 靜態分派 = 根據 變量的靜態類型 確定執行(重載)哪個方法

  • 所以上述的方法執行時,是根據變量(man、woman)的靜態類型(Human)確定重載sayHello()中參數為Human guy的方法,即sayHello(Human guy)

特別注意

a. 變量的靜態類型 發生變化 的情況

可通過 強制類型轉換 改變 變量的靜態類型

Human?man?=?new?Man();?
test.sayHello((Man)man);?
//?強制類型轉換
//?此時man的靜態類型從?Human?變為?Man
//?所以會調用sayHello()中參數為Man?guy的方法,即sayHello(Man?guy)

b. 靜態分派的優先級匹配問題

  • 問題描述:

  • 背景 現需要進行靜態分派

  • 問題 程序中 沒有顯示指定 靜態類型

  • 解決方案 程序會根據 靜態類型的優先級 從而選擇 優先的靜態類型進行方法分配。

實例說明

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");??
????}??
//?測試代碼
????public?static?void?main(String[]?args)?{??
????????sayHello('a');??
????}??
}??
//?運行結果
hello?char

因為‘a’是一個char類型數據(即靜態類型是char),所以會選擇參數類型為char的重載方法。

若注釋掉sayHello(char arg)方法,那么會輸出

hello?int

因為‘a’除了可代表字符串,還可代表數字97。因此當沒有最合適的sayHello(char arg)方式進行重載時,會選擇第二合適(第二優先級)的方法重載,即 sayHello(int arg)

總結:當沒有最合適的方法進行重載時,會選優先級第二高的的方法進行重載,如此類推。

優先級順序為:

char>int>long>float>double>Character>Serializable>Object>...

其中...為變長參數,將其視為一個數組元素。變長參數的重載優先級最低。

因為 char 轉型到 byteshort 的過程是不安全的,所以不會選擇參數類型為byteshort的方法進行重載,故優先級列表里也沒有。

特別注意

  • 上面講解的主要是 基本數據類型的優先級匹配問題

  • 若是引用類型,則根據 繼承關系 進行優先級匹配

注意只跟其編譯時類型(即靜態類型)相關

3. 動態分派

  • 定義 根據 變量的動態類型 進行方法分派 的 行為

即根據 變量的動態類型 確定執行哪個方法

  • 應用場景 方法重寫(Override

  • 實例說明

//?定義類
????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");?
????????}?
????}?
//?測試代碼
????public?static?void?main(String[]?args)?{?
????????//?情況1
????????Human?man?=?new?man();?
????????man.sayHello();?
????????//?情況2
????????man?=?new?Woman();?
????????man.sayHello();?
????}?
}
//?運行結果
man?say?hello
woman?say?hello
//?原因解析
//?1.?方法重寫(Override)?=?動態分派?=?根據?變量的動態類型?確定執行(重寫)哪個方法
//?2.?對于情況1:根據變量(Man)的動態類型(man)確定調用man中的重寫方法sayHello()
//?3.?對于情況2:根據變量(Man)的動態類型(woman)確定調用woman中的重寫方法sayHello()

特別注意

對于代碼中:

Human?man?=?new?Man();?
man?=?new?Woman();?
man.sayHello();?
//?man稱為執行sayHello()方法的所有者,即接受者。
  • invokevirtual指令執行的第一步 = 確定接受者的實際類型

  • invokevirtual指令執行的第二步 = 將 常量池中 類方法符號引用 解析到不同的直接引用上

第二步即方法重寫(Override)的本質

4. 二者區別

怎么使用java?JVM方法分派模型  java 第1張

關于“怎么使用java?JVM方法分派模型”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“怎么使用java?JVM方法分派模型”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注蝸牛博客行業資訊頻道。

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:niceseo99@gmail.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

評論

日本韩欧美一级A片在线观看