Java多態的實現原理

參考博客:java

【解惑】Java動態綁定機制的內幕http://blog.csdn.net/zero_295813128/article/details/52117737 程序員

Java 虛擬機體系結構:http://hxraid.iteye.com/blog/676235

--------------------------------------------------------------------------------------------------數組

下面是本身的理解總結:數據結構

    首先得對兩個概念有理解方法區和常量池。這兩個都是Java虛擬在運行時的數據區域,常量池是方法區ide

的一部分。編碼

方法區spa

    方法區與Java堆同樣,是各個線程共享的內存區域,用於存儲已經被虛擬機加載的類信息、常量、靜態變
.net

量、即便編譯器編譯後的代碼等數據。線程

常量池指針

    常量池是方法區的一部分,用於存放編譯期所生成的各類字面量和符號引用。常量池中共有11個常量表。

    常量表類型 標誌值(佔1 byte) 描述

    CONSTANT_Utf8     1 UTF-8編碼的Unicode字符串

    CONSTANT_Integer 3 int類型的字面值

    CONSTANT_Float     4 float類型的字面值

    CONSTANT_Long     5 long類型的字面值

    CONSTANT_Double     6 double類型的字面值

    CONSTANT_Class     7 對一個類或接口的符號引用

    CONSTANT_String     8 String類型字面值的引用

    CONSTANT_Fieldref 9 對一個字段的符號引用

    CONSTANT_Methodref 10 對一個類中方法的符號引用

  CONSTANT_InterfaceMethodref 11 對一個接口中方法的符號引用

    CONSTANT_NameAndType 12 對一個字段或方法的部分符號引用

---------------------------------------------------------------------------------------------------

對於多態的原理主要研究方法區。在Java中多態指的是它容許基類的指針或引用指向派生類的對象,而在具體訪

問時實現方法的動態綁定。java中的方法調用有靜態綁定和動態綁定之分,靜態綁定指的是咱們在編譯期就已經

肯定了會執行那個方法的字節碼,而動態綁定只有在運行時才能知曉。

靜態綁定

    Java中的靜態方法、私有方法以及final修飾的方法的調用,都屬於靜態綁定,對於重載的實例方法的

調用,也是採用靜態綁定。靜態綁定的原理主要是一個常量池解析的過程,下面來詳解其過程:

    假若有兩個類A、B,在A類中咱們調用了B類中的一個靜態方法,在編譯期,這個調用的動做會被編譯成一

條靜態調用指令,該指令就對應常量池中的CONSTANT_Methodref表中所存儲的該方法的符號引用,經過這個符號引用

能夠獲得靜態方法的全類名B,JVM加載B類,便會獲得B類中方法的直接地址,該地址會被存儲到A類常量池中對應的

常量表中,這即是常量池解析過程,再次發起調用時,就會直接根據這個直接地址調用對應方法。

    以上過程能夠看出,在編譯階段咱們就已經肯定了應該執行哪個字節碼代碼。

動態綁定

    動態綁定講解以前須要瞭解JVM管理的一個重要的數據結構--方法表。它以數組的形式記錄了當前類及其全部

超類的可見方法字節碼在內存中的直接地址 。

    動態綁定前面的流程與靜態綁定相似,假如此處有兩個類A,B繼承了A類,B類中重寫了A類中的f1()方法,咱們採用

向上轉型的方式用指向B實例的A類型引用調用f1()方法,編譯器會生成一條字節碼指令,該指令會去常量表中找到f1()方法信

息的符號引用,經過該引用肯定調用該方法的類型全名,即A類的全名稱,根據名稱加載到A類的字節碼,去A類所對應的方法

表中找到f1()方法,將它的直接地址記錄到調用f1()方法的類的對應的常量表中,常量池解析結束,能夠思考,咱們此時是否能

肯定調用f1()方法時執行的是哪一塊的字節碼,答案是不能,由於截至此時咱們f1()方法指定執行的是父類中的方法,引用雖然

父類類型,但他指向的是父類對象仍是子類對象是不知道的(確切地說是此時的程序不知道,程序員確定是知道的),假如指向父類

那就是父類中的f1()方法,若是指向子類的實例,子類沒有重寫,依然執行父類f1()方法,若是子類重寫了就應該是子類的f1()

方法。此時動態綁定就登場了,肯定f1()換須要拿到B類實例在堆中的引用,經過引用找到堆中B的對象,根據對象進一步獲取它的

方法表,找到方法表的f1()方法的直接地址,此時便最終肯定了。

相關文章
相關標籤/搜索