天天看點

Java的靜态綁定&動态綁定

java多态具體表現形式有兩種:方法的重寫和方法的重載。先來看一段程式:

public class Main {
    public static void main(String[] args) {
        Base b=new Base();
        Derived d=new Derived();
        whichFoo(b, b);
        whichFoo(b, d);
        whichFoo(d, b);
        whichFoo(d, d);
    }
    public static void whichFoo(Base arg1,Base arg2){
        arg1.foo(arg2);
    }
}
class Base{
    public void foo(Base x){
        System.out.println("Base.Base");
    }
    public void foo(Derived x){
        System.out.println("Base.Derived");
    }
}
class Derived extends Base{
    public void foo(Base x){
        System.out.println("Derived.Base");
    }
    public void foo(Derived x){
        System.out.println("Derived.Derived");
    }
}
           

它的輸出結果是:

Base.Base
Base.Base
Derived.Base
Derived.Base
           

這是因為在Java中,一個方法的參數在編譯階段常被靜态地綁定,在whichFoo方法中,形式參數arg2的類型是Base, 是以不管arg2實際引用的是什麼類型,arg1.foo(arg2)比對的foo都将是foo(Base),而要知道arg1引用的對象時,這是在運作階段由JVM決定的,稱為動态綁定。

再來看下面一段程式:

public class Main {
    public static void main(String[] args) {
        Father father=new Son();
        System.out.println(father.age);
        father.name();
        father.age();
    }
}
class Father{
    public int age = ;
    public static void name(){
        System.out.println("father name");
    }
    public void age(){
        System.out.println("father age:"+age);
    }
}
class Son extends Father{
    public int age = ;
    public static void name(){
        System.out.println("son name");
    }
    public void age(){
        System.out.println("Son age:"+age);
    }
}
           

輸出結果為:

60
father name
Son age:25
           

解釋如下:

當執行 Father father=new Son();發生了向上轉型,在編譯期間 father就是個Father對象,系統不知道實際上它是一個 Son對象,這得在運作期間由JVM判斷

在我們調用father.age的時候實際上,在處理java類中的成員變量時,并不是采用運作時綁定,而是一般意義上的靜态綁定,即調用的是Father類的age成員變量

在調用father.name()的時候,注意這是個static方法,java當中的方法final,static,private和構造方法是前期綁定,是以調用的是Father類中的name方法

在調用father.age()的時候,需要采用動态綁定,此時father會被解析成它實際的對象,即Son對象,是以實際調用的是Son.age()