作了一次筆試題,發現了一題問答題,是關於Java
綁定的:html
當時作的時候是徹底不會的。。。java
因而這裏補上一篇Java
綁定的文章。app
首先來了解一下綁定的概念。綁定是指一個方法的調用與方法所在的類關聯起來。jvm
很抽象吧,舉個例子,若是父類與子類存在同名方法,子類對父類方法進行了重寫,那麼就須要綁定來區分調用的究竟是父類的方法仍是子類的方法。相對簡單的一種理解是,綁定是一個方法的調用與調用這個方法的類鏈接在一塊兒的過程。ide
而綁定具體又能夠分爲:spa
靜態綁定也叫前期綁定、編譯期綁定,在程序運行以前,也就是編譯時期JVM
可以確認方法由誰調用,這種機制就叫靜態綁定。code
若是一個方法由private
、static
、final
任意一個關鍵字修飾,那麼這個方法就是靜態綁定的,緣由很簡單,由於:htm
private
修飾的方法,沒法由本類之外的類調用,也就是調用者只能是該類static
修飾的方法,經過類名.方法名
進行調用,也能夠惟一肯定了調用的類final
修飾的方法,不能被子類進行重寫,在編譯期就能肯定了調用的類這三個關鍵字修飾的方法,均可以在編譯時期就能惟一肯定了調用的類,不存在子類調用的問題,所以使用靜態綁定,而不是動態綁定。對象
動態綁定就是運行時根據對象的類型進行綁定,簡單來講,JVM
在運行時期決定由哪一個對象調用的過程稱爲動態綁定。blog
好比:
public class Main { public static void main(String[] args){ A b = new B(); b.print(); } } class A{ public void print(){ System.out.println("A"); } } class B extends A{ @Override public void print(){ System.out.println("B"); } }
因爲B類繼承了A類,所以建立對象的時候:
A b = new B();
編譯期並不知道b真正引用的是A類仍是B類,在運行的時候才知道b是一個A類對象,可是指向了B類的引用。
在Java
中,全部的非final
、private
、static
的方法都是動態綁定的,由於只要繼承了就能重寫。
在瞭解動態綁定的過程以前,先了解一些前置知識。
Java
中的方法調用有兩類:
而方法調用的指令有四個,分別是:
invokestatic
invokespecial
invokevirtual
invokeinterface
前兩個是靜態綁定的,然後兩個是動態綁定的。
方法表是字節碼文件的一部分,每一個類都有一個方法表,方法表是爲invokevirtual
以及invokeinterface
指令服務的。因爲Java
中的類都繼承於Object
,所以,在默認狀況下,全部類的方法表中都有Object
的方法,若是重寫了其中的方法,就會改變其中的描述符。好比,Object
類的方法表能夠簡單理解以下:
而加載了A類的字節碼後,由於A類並無重寫任何的Object
方法,所以只是添加了A類自己的方法:
而加載了B類的字節碼後,由於重寫了print()
,所以方法表以下:
瞭解了前置知識後看具體過程就會相對簡單一點了,動態綁定的過程能夠分爲三步:
JVM
獲取到對象的實際類型後,再獲取該類型的方法表b.print()
時,經過方法表發現實際方法是B.print()
B.print()