Java中的綁定

1 前言

作了一次筆試題,發現了一題問答題,是關於Java綁定的:html

在這裏插入圖片描述

當時作的時候是徹底不會的。。。java

因而這裏補上一篇Java綁定的文章。app

2 綁定

首先來了解一下綁定的概念。綁定是指一個方法的調用與方法所在的類關聯起來jvm

很抽象吧,舉個例子,若是父類與子類存在同名方法,子類對父類方法進行了重寫,那麼就須要綁定來區分調用的究竟是父類的方法仍是子類的方法。相對簡單的一種理解是,綁定是一個方法的調用與調用這個方法的類鏈接在一塊兒的過程。ide

而綁定具體又能夠分爲:spa

  • 靜態綁定:就是程序執行前,方法已經被綁定,能夠簡單理解成編譯期綁定
  • 動態綁定:在運行時根據具體對象的類型進行綁定,經過一些機制去運行時判斷對象的類型,並分別調用適當的方法

3 靜態綁定

靜態綁定也叫前期綁定、編譯期綁定,在程序運行以前,也就是編譯時期JVM可以確認方法由誰調用,這種機制就叫靜態綁定。code

若是一個方法由privatestaticfinal任意一個關鍵字修飾,那麼這個方法就是靜態綁定的,緣由很簡單,由於:htm

  • private修飾的方法,沒法由本類之外的類調用,也就是調用者只能是該類
  • static修飾的方法,經過類名.方法名進行調用,也能夠惟一肯定了調用的類
  • final修飾的方法,不能被子類進行重寫,在編譯期就能肯定了調用的類

這三個關鍵字修飾的方法,均可以在編譯時期就能惟一肯定了調用的類,不存在子類調用的問題,所以使用靜態綁定,而不是動態綁定。對象

4 動態綁定

動態綁定就是運行時根據對象的類型進行綁定,簡單來講,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中,全部的非finalprivatestatic的方法都是動態綁定的,由於只要繼承了就能重寫。

5 區別

  • 發生時期:靜態綁定發生在編譯時期,動態綁定發生在運行時期
  • 靈活性:動態綁定的靈活性要比靜態綁定高,由於靜態綁定在編譯的時期就肯定了,而動態綁定在編譯的時候並不知道是調用哪個類的方法
  • 速度:靜態綁定調用方法的速度要快於動態綁定,由於靜態綁定能夠直接調用,而動態綁定須要去搜索方法表

6 動態綁定的過程

在瞭解動態綁定的過程以前,先了解一些前置知識。

6.1 方法調用

Java中的方法調用有兩類:

  • 靜態方法調用
  • 動態方法調用

而方法調用的指令有四個,分別是:

  • invokestatic
  • invokespecial
  • invokevirtual
  • invokeinterface

前兩個是靜態綁定的,然後兩個是動態綁定的。

6.2 方法表

方法表是字節碼文件的一部分,每一個類都有一個方法表,方法表是爲invokevirtual以及invokeinterface指令服務的。因爲Java中的類都繼承於Object,所以,在默認狀況下,全部類的方法表中都有Object的方法,若是重寫了其中的方法,就會改變其中的描述符。好比,Object類的方法表能夠簡單理解以下:

在這裏插入圖片描述

而加載了A類的字節碼後,由於A類並無重寫任何的Object方法,所以只是添加了A類自己的方法:

在這裏插入圖片描述

而加載了B類的字節碼後,由於重寫了print(),所以方法表以下:

在這裏插入圖片描述

6.3 具體過程

瞭解了前置知識後看具體過程就會相對簡單一點了,動態綁定的過程能夠分爲三步:

  • 虛擬機提取對象實際類型的方法表:JVM獲取到對象的實際類型後,再獲取該類型的方法表
  • 虛擬機搜索方法簽名:當調用b.print()時,經過方法表發現實際方法是B.print()
  • 調用方法:調用B.print()

7 參考

相關文章
相關標籤/搜索