首頁  >  文章  >  Java  >  07.Java 基礎 - 靜態綁定&動態綁定

07.Java 基礎 - 靜態綁定&動態綁定

黄舟
黄舟原創
2017-02-27 10:29:531240瀏覽

基本概念

綁定,指的是方法的呼叫與其所在的類別關聯起來。

綁定可分為靜態綁定和動態綁定。

在分析靜態綁定和動態綁定之前需要知道的幾個概念:

  • #編譯期:編譯過程是將Java 來源文件編譯成字節碼(.class文件,JVM 可執行程式碼)的過程,在這個過程中Java是不與記憶體打交道的,在這個過程中編譯器會進行語法的分析,如果語法不正確就會報錯。

  • 運行期:運行過程是指JVM(Java虛擬機)裝載字節碼檔案並解釋執行,在這個過程才是真正的創建內存,執行Java程式。


方法呼叫

Java 的方法呼叫過程如下:

  • 編輯器查看物件的宣告類型和方法名。取得所有可能被呼叫的候選方法,因為在方法重載的情況。例如:方法一為 print(String str)、方法二為 print(int )。

  • 編譯器查看呼叫方法的入參類型。從候選方法中挑選匹配的方法。例如入參為 “hello”,則挑選 print(String str)。

  • 若方法是 private、static、final 修飾或建構函數,編譯器可以決定要呼叫哪個方法。這是靜態綁定。

  • 如果不是上述情況,就要使用執行階段(動態)綁定。


靜態綁定

靜態綁定,又稱為前期綁定,編譯時綁定。表示編譯期進行的綁定,即程式運行前方法已被綁定。

只有被final,static,private 修飾的方法、成員變數、建構方法是靜態綁定:

##類型finalprivatestatic成員變數建構方法來看下面的這個範例:
##解釋
被其修飾的方法可以被繼承,但不能被重寫;子類別物件可以調用,但是調用的是父類別中定義的那個方法;間接表示將方法宣告為final 可以避免重寫,關閉動態綁定。
被其修飾地方法隱含地包含了 final 關鍵字。由於它對外是不可見的,所以不能被繼承,重寫;只能透過類別本身的物件來調用,因此在方法運行之前就可以明確物件。
靜態方法是依賴類別而依賴物件的。它可以被子類別繼承(實質是被子類別隱藏),但是不能被子類別重寫。當子類別物件向上轉型為父類別物件時,不論子類別中有沒有定義這個靜態方法,該物件都會使用父類別中的靜態方法。因此這裡說靜態方法可以被隱藏。
預設 Java 對屬性採用靜態綁定,這樣在編譯期就能發現程式錯誤,能夠提供效率。
建構方法不能被繼承的,子類別繼承父類別時預設要先呼叫父類別的建構方法(無論顯示或隱含)。因此在程式運行之前就可以知道構造方法術語哪個物件。
// 父类class Parent{    // 变量
    String name="Parent";    // 静态方法
    static void print(){
        System.out.println("Parent print");
    }    // 私有方法
    private void say(){
        System.out.println("Parent say");
    }    // 终态方法
    final void look(){
        System.out.println("Parent look");
    }
}// 子类class Son extends Parent{
    String name ="Son";    static void print(){
        System.out.println("Son print");
    }    // 编译错误,无法重写父类的 final方法
    final void look(){};
}public class Test{
    public static void main(String[] args) {        // 发生向上转型
        Parent p = new Son();        // 输出 Parent
        System.out.println(p.name);        // 输出 Parent print
        p.print();        // 编译错误,对外不可见
        p.say();
    }
}


#動態綁定

動態綁定,又稱後期綁定,運行時綁定;表示在運行時根據具體對象的類型進行綁定。

動態綁定的過程:

    虛擬機提取物件的實際類型的方法表;
  • 虛擬機器搜尋方法簽章;
  • 呼叫方法。
  • 下面來看一個範例:
class A {    int x = 5;
}

class B extends A {    int x = 6;
}

class Parent {    public A getValue() {
        System.out.print("Parent Method ");        return new A();
    }
}

class Son extends Parent {    public B getValue() {
        System.out.print("Son Method ");        return new B();
    }
}public class Test {
    public static void main(String[] args) {        // 向上转型
        Parent p = new Son();        // 输出结果:Son Method 5
        // 注意:是 5 不是 6 !
        System.out.println(p.getValue().x);
    }
}

觀察輸出分析如下:

    p.getValue( ) ,由於發生了向上轉型,因此它有先從子類別(Son)找到該方法,此時呼叫的是Son 的方法。這裡屬於動態綁定。
  • p.getValue( ).x,由於 x 屬於成員變量,因此在程式運行之前就確定了它的物件(屬於Parent),這裡是發生了靜態綁定。
  • 如果還不明白,再來看一個範例:
class Parent {
    String name = "Parent " + this.getClass().getName();
}

class Son extends Parent {
    String name = "Son" + this.getClass().getName();
}public class Test {
    public static void main(String[] args) {        // 向上转型
        Parent p = new Son();        // 输出:Parent Son
        System.out.println(p.name);
    }
}

觀察輸出結果分析如下:

    p.name :name 是成員變量,此時發生靜態綁定,因此呼叫的是Parent 的屬性。
  • this.getClass( ):getClass 是方法,由於此時發生了向上轉型,預設程式會從子類別開始查找該方法,而正好子類別也存在該方法。因此呼叫的是子類別的方法,此時發生了動態綁定。

 以上就是07.Java 基礎- 靜態綁定&動態綁定的內容,更多相關內容請關注PHP中文網(www. php.cn)!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn