【Java學習】Java方法的靜態綁定與動態綁定講解

轉載請註明原文地址:http://www.cnblogs.com/ygj0930/p/6554103.html

    一:綁定

        把一個方法與其所在的類/對象 關聯起來叫做方法的綁定。綁定分爲靜態綁定(前期綁定)和動態綁定(後期綁定)。

   

    二:靜態綁定

        靜態綁定(前期綁定)是指:在程序運行前就已經知道方法是屬於那個類的,在編譯的時候就可以連接到類的中,定位到這個方法。

        在Java中,final、private、static修飾的方法以及構造函數都是靜態綁定的,不需程序運行,不需具體的實例對象就可以知道這個方法的具體內容。

 

    三:動態綁定

        動態綁定(後期綁定)是指:在程序運行過程中,根據具體的實例對象才能具體確定是哪個方法。

        動態綁定是多態性得以實現的重要因素,它通過方法表來實現:每個類被加載到虛擬機時,在方法區保存元數據,其中,包括一個叫做 方法表(method table)的東西,表中記錄了這個類定義的方法的指針,每個表項指向一個具體的方法代碼。如果這個類重寫了父類中的某個方法,則對應表項指向新的代碼實現處。從父類繼承來的方法位於子類定義的方法的前面。

        動態綁定語句的編譯、運行原理:我們假設 Father ft=new Son();  ft.say();  Son繼承自Father,重寫了say()。

        1:編譯:我們知道,向上轉型時,用父類引用執行子類對象,並可以用父類引用調用子類中重寫了的同名方法。但是不能調用子類中新增的方法,爲什麼呢?

                     因爲在代碼的編譯階段,編譯器通過 聲明對象的類型(即引用本身的類型) 在方法區中該類型的方法表中查找匹配的方法(最佳匹配法:參數類型最接近的被調用),如果有則編譯通過。(這裏是根據聲明的對象類型來查找的,所以此處是查找 Father類的方法表,而Father類方法表中是沒有子類新增的方法的,所以不能調用。)

                     編譯階段是確保方法的存在性,保證程序能順利、安全運行。

        2:運行:我們又知道,ft.say()調用的是Son中的say(),這不就與上面說的,查找Father類的方法表的匹配方法矛盾了嗎?不,這裏就是動態綁定機制的真正體現。

                     上面編譯階段在 聲明對象類型 的方法表中查找方法,只是爲了安全地通過編譯(也爲了檢驗方法是否是存在的)。而在實際運行這條語句時,在執行 Father ft=new Son(); 這一句時創建了一個Son實例對象,然後在 ft.say() 調用方法時,JVM會把剛纔的son對象壓入操作數棧,用它來進行調用。而用實例對象進行方法調用的過程就是動態綁定:根據實例對象所屬的類型去查找它的方法表,找到匹配的方法進行調用。我們知道,子類中如果重寫了父類的方法,則方法表中同名表項會指向子類的方法代碼;若無重寫,則按照父類中的方法表順序保存在子類方法表中。故此:動態綁定根據對象的類型的方法表查找方法是一定會匹配(因爲編譯時在父類方法表中以及查找並匹配成功了,說明方法是存在的。這也解釋了爲何向上轉型時父類引用不能調用子類新增的方法:在父類方法表中必須先對這個方法的存在性進行檢驗,如果在運行時才檢驗就容易出危險——可能子類中也沒有這個方法)。

 

    四:區分

        程序在JVM運行過程中,會把類的類型信息、static屬性和方法、final常量等元數據加載到方法區,這些在類被加載時就已經知道,不需對象的創建就能訪問的,就是靜態綁定的內容;需要等對象創建出來,使用時根據堆中的實例對象的類型才進行取用的就是動態綁定的內容。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章