1. 程式人生 > >多型的底層原因

多型的底層原因

目錄

靜態分派

動態分派

動態分配的實現


多型的底層就是分派,分派分為靜態分派(過載)與動態分派(重寫)。

靜態分派

發生在編譯時期,因此靜態分派的動作實際上不是由虛擬機器來執行的,只能通過語言上的規則去理解和推斷哪個是更加合適的版本,自動轉型: char->int->long->float->double的順序轉型時進行匹配,但不會匹配到byte和short型別的轉型時不安全的。如果經過基本型別的順序還未找到那麼就會發生一次自動裝箱,去尋找自己的裝箱類,如果找不到了裝箱類,但是找到了裝箱類實現的介面型別也可以,如果出現兩個優先順序一樣就會報錯,拒絕編譯。越接近上層的優先順序越低。

動態分派

  • 實際型別變化的結果在執行期才確定,編譯器在編譯程式的時候並不知道一個物件的實際型別是什麼。

  • 找到運算元棧頂的第一個元素所指向的物件的實際型別,記做C。
  • 如果在型別C中找到與常量中的描述符和簡單名稱都相符的想法,則進行訪問校驗,如果通過則返回這個方法的直接引用,查詢過程結束;如果不通過,則返回異常。
  • 否則,按照繼承關係從下往上一次對C的各個父類進行第2步的搜尋和驗證過程。
  • 如果始終沒有找到合適的方法,則丟擲異常。

Java是一種靜態多分派,動態單分派的語言。靜態多分派,選擇目標方法的依據有兩點:一個是靜態型別,一個是方法引數。動態單分派則是唯一影響虛擬機器選擇的性因素只有此方法的接受者的實際型別是什麼作為選擇依據。

動態分配的實現

因為動態分派是非常頻繁的動作,而且動態分派的方法版本選擇過程中需要執行時在類的方法元資料中搜索合適的目標方法,因此在虛擬機器的實際實現中基於效能的考慮,大部分都不會真正的進行如此頻繁的搜尋,最常用的手段就是可以給寶寶過一遍 類在方法區中建立一個虛方法表,使用虛方法表索引來代表元資料查詢以提高功能。

虛方法表中存放著各個方法的實際入口地址,如果某個方法在子類中沒有被重寫,那麼子類的虛方法表裡面的地址入口和父類相同方法的地址入口都是一致的,都指向父類的實現入口。如果子類重寫了這個方法,子類方法表中的地址會替換為指向子類實現版本2的入口地址。

 

 

參考書本

深入理解Java虛擬機器