1. 程式人生 > >前期繫結 和 後期繫結

前期繫結 和 後期繫結

thinking in java 讀書筆記(感悟);
頁碼:P9 (想看書上怎麼講的。自行翻看 P9 頁)

寫於:2018年3月29日19:22:14

作者:淮左白衣

目錄

場景:

 public void eat(Animal animal){
        System.out.println(animal.eatSometing());
    }

    ....
    ....

    Dog dog = new Dog();
    eat(dog);
    Cat cat = new Cat();
    eat(cat);

一眼就可以看出,這是多型;在多型的時候,我們將子類的型別向上轉型為父類,進行型別的泛化,便於我們寫出實用性很強的程式碼(新型別產生,不用修改原有程式碼);
就像這裡 eat

方法,接受一個 Animal型別 ;我們傳進去的分別是 dogcat ;但是打印出的結果是明確的,傳dog進去,輸出狗吃骨頭,傳cat進去,輸出貓吃魚
但是這裡有個問題,不知道大家想過沒有:任何型別傳進去,都是父型別,但是在呼叫方法的時候,卻是明明確確的呼叫了子類的方法!或者 編譯器是怎麼知道,具體該呼叫哪一個方法的呢?
這就是本文要講的 前期繫結後期繫結

前期繫結

前期繫結是 面向過程 語言的編譯器的做法 ;編譯器在 編譯 面向過程語言的時候,在出現 函式調 用的時候,會產生一個 對具體函式名字的引用 ,這樣在程式執行的時候,執行到函式呼叫的語句,就會發現這裡一個 對XXX方法的引用

,就會把執行邏輯解析到這個XXX方法的絕對地址上;

但是這一套,到java這就不好使了,編譯器在編譯程式碼的時候,知道具體呼叫哪一個方法嗎?編譯器不是神,它不可能知道的;

因此,我們需要另謀蹊徑,偉大的電腦科學家,想到了 後期繫結

後期繫結

既然編譯時期,編譯器搞定不了方法呼叫的問題!那麼,就在執行期,做手腳,來搞定這件事;

java是這樣來搞定方法呼叫的在每一個物件中儲存一小段資訊,通過這一小段資訊,可以計算出該物件的方法地址 ;然後去呼叫方法

因此上述程式碼的呼叫就可以得到理解:雖然傳進去的都是 Animal引用但是引用指向的物件是Dog、Cat物件,這個物件裡面儲存了資訊;比如Dog物件,裡面就儲存它的eatSomething方法在哪裡

;這樣虛擬機器就會呼叫正確的方法了 ;

順便講下 編譯看左邊,執行看右邊 的背後是什麼意思吧 ;

編譯看左邊,執行看右邊

這句話,好多人都知道的,但是為什麼呢

其實這就是後期繫結的原因 ;java的編譯器,雖然在編譯期間不能為方法呼叫做些什麼,但是也不能啥也不幹吧 ;(它要是不幹了,虛擬機器可能就不開心了,憑啥都是我在做事呀o(╥﹏╥)o) ;

java的編譯器在編譯期間,會檢查這個要呼叫的方法是否存在,呼叫的引數是否正確 ;返回的型別是否正確;簡單說,就是做一些檢查工作 ;

這個檢查工作,就是為什麼編譯看左邊;假如父類沒有這個方法,編譯時過不去的,因為編譯器對方法是否存在進行檢查;執行看右邊,是因為後期繫結,去呼叫具體的方法了 ;