文章插圖

文章插圖
由于多態需要通過動態綁定才能得以實現,而綁定通俗一點講就是讓不同的對象對同一個函數進行調用,或者反過來講,就是讓同一個函數與不同的對象綁定起來,所以多態得以實現的一個大前提就是,編程語言必須是面向對象的 。同時,函數與對象相互綁定,意味著函數也屬于對象的一部分,這便具備了封裝的特性 。因為有了封裝,才有了對象 。同時,一個函數能夠綁定多個對象,意味著對各不同的對象具有相同的行為,這是繼承的含義 。因此,面向對象的三大特性缺一不可 。封裝與繼承其實是為了多態準備的,或者說,封裝與繼承成全了多態,多態讓封裝與繼承的意義最大化 。
【java 虛函數 純虛函數 java純虛函數】C++是如何實現多態的
多態的實現,現在幾乎所有的編程語言都是基于虛表實現的,英文vtable 。
C++的虛表在哪呢?在new創建的對象的頭部 。
虛表里面存儲的是什么呢?是虛函數
搞清楚了虛表,再來了解虛表分發就容易多了 。虛表分發,其實就是通過虛表內存地址拿到虛表記錄,然后通過函數名+內含參數信息及返回值信息的簽名去虛表中找 。因為是從前往后找,所以如果子類重寫了父類的方法,會調用子類的方法 。
所以Java雖好,底層也很重要 。順便說下,虛表就是用數組實現的,沒有有些小伙伴想得那么復雜 。
JVM中的虛表
JVM的虛表跟C++的虛表還不太一樣 。不一樣體現在哪呢?研究虛表研究三個東西:虛表在哪、虛表是用什么結構實現的、虛表分發機制是怎樣的 。JVM的虛表分發等下講,JVM的虛表也是用數組實現的,那這個不一樣就體現在虛表在哪?
Java的類,JVM中對應的C++對象是klass模型 。Java的對象,JVM中對應的C++對象是oop模型 。C++中的虛表在對象頭中,而JVM的虛表在klass模型的頭部,即Java類對象的頭部 。這點區別一定要記住,這樣你才能理解Java對象的內存布局 。
問個問題:我們隨便定義的一個類,它有沒有JVM虛表呢?其實是有的 。那是哪些方法的內存地址呢?回答這個問題前先得搞明白:什么樣的方法會存入虛表 。只有public、protect類型的,且不被static、final修飾的方法才能被多態調用,才會進入虛表 。因為Java中所有的類都是Object的子類,所以Object中滿足這個條件的方法都會在每個類的虛表中 。
又到了小伙伴不服氣環節 。沒事,上證據 。具體怎么查看我就不講了,有點復雜 。對hotspot沒一定的功力講了也沒概念 。
JVM實現虛表分發,對應的字節碼指令有兩個:invokevirtual、invokeinterface 。上篇文章咱們深入講解了invokeinterface,這篇文章咱們繼續拿這個指令來講這個知識點 。我們來看看JVM是如何分發的 。其實一看執行invokeinterface時的堆棧,你應該就能明白了 。
- 虛擬機主機配置推薦 如何選擇虛擬主機
- mysql jar包下載安裝教程 java導入mysql驅動包
- JavaScript獲取div高度 css獲取div高度
- java中將字符串分割成數組 java把一串數字拆分成數組
- 二次函數判別式的由來 二次函數的判斷式
- c語言字符串輸入函數gets的編寫 C語言字符串輸入函數
- 驗證文件路徑用哪個方法 java驗證文件路徑用哪個方法獲取路徑
- java文件的讀取和寫入 java文件讀入寫出
- java簡歷如何寫 java開發工程師簡歷怎么寫
- php數組的長度 php使用什么函數可以求得數組的大小
