天天看點

java — 靜态綁定和動态綁定

  綁定:一個方法的調用與方法所在的類關聯起來。java中的綁定分為靜态綁定和動态綁定,又被稱作前期綁定和後期綁定。

  靜态綁定:(final、static、private)在程式執行前已經被綁定,也就是說在編譯過程中就已經知道這個方法是哪個類的方法,此時由編譯器擷取其他連接配接程式實作。

  動态綁定:在運作根據具體對象的類型進行綁定。

1.靜态綁定

  private:不能被繼承,則不能通過子類對象調用,而隻能通過類本身的對象進行調用,是以可以說private方法和方法所屬的類綁定;

  final:final方法雖然可以被繼承,但是不能被重寫(覆寫),雖然子類對象可以調用,但是調用的都是父類中的final方法(是以可以看出當類中的方法聲明為final的時候,一是為了防止方法被覆寫,而是為了有效關閉java的動态綁定);

  static:static方法可以被子類繼承,但是不能被子類重寫(覆寫),但是可以被子類隐藏。(這裡意思是說如果父類裡有一個static方法,它的子類裡如果沒有對應的方法,那麼當子類對象調用這個方法時就會使用父類中的方法。而如果子類中定義了相同的方法,則會調用子類的中定義的方法。唯一的不同就是,當子類對象上轉型為父類對象時,不論子類中有沒有定義這個靜态方法,該對象都會使用父類中的靜态方法。是以這裡說靜态方法可以被隐藏而不能被覆寫。這與子類隐藏父類中的成員變量是一樣的。隐藏和覆寫的差別在于,子類對象轉換成父類對象後,能夠通路父類被隐藏的變量和方法,而不能通路父類被覆寫的方法)。

2.動态綁定

  調用的方法依賴于隐式參數的實際類型,并且在運作時實作動态綁定。動态綁定的過程分為以下幾個環節:

  (1)編譯器檢視對象的聲明類型和方法名;

  (2)編譯器檢視調用方法時提供的參數類型。例如x.f("hello"),編譯器将會挑選f(String),而不是f(int),由于存在類型轉換(int轉換為double),是以可能會更複雜。如果編譯器沒找到參數類型比對的方法,或者發現有多個方法與之比對,就會報告一個錯誤。

  至此,編譯器獲得了需要調用的方法名字和參數類型。

  (3)采用動态綁定調用方法的時候,一定調用與所引用對象的實際類型最合适的類的方法。如果x的實際類型是D,它是C類的子類,如果D定義了一個方法f(String),就直接調用它,否則将在D類的超類中尋找f(String),以此類推。

  每次調用方法都要進行搜尋,時間開銷太大,是以虛拟機預先為每個類建立一個方法表(method table),其中列出了所有方法的簽名和實際調用的方法。這樣在調用方法的時候,隻需要查找這個表即可。

能讓一個男孩子熱血的,不僅有夢想,還有姑娘。