運行時綁定也叫動態綁定,它是一種調用對象方法的機制。Java調用對象方法時,一般采用運行時綁定機制。
1.Java的方法調用過程
編譯器查看對象的聲明類型和方法名(對象變量的聲明類型)。通過聲明類型找到方法列表。
編譯器查看調用方法時提供的參數類型。
如果方法是private、static、final或者構造器,編譯器就可以確定調用那個方法。這是靜態綁定。
如果不是上述情況,就要使用運行時(動態)綁定。在程序運行時,采用動態綁定意味著:虛擬機將調用對象實際類型所限定的方法。
2.運行時(動態)綁定的過程
虛擬機提取對象的實際類型的方法表;
虛擬機搜索方法簽名;
調用方法。
注意,這裡說的是對象的實際類型。即在多態的情況下,虛擬機可以找到所運行對象的真正類型。
3.在向上轉型情況下的動態綁定示例
public class Father {
public void method() {
System.out.println("父類方法,對象類型:" + this.getClass());
}
}
public class Son extends Father {
public static void main(String[] args) {
Father sample = new Son();//向上轉型
sample.method();
}
}
結果1:
父類方法,對象類型:class samples.Son
這個結果沒有疑問,聲明的是父類的引用(句柄),但准確的調用了子類的對象,調用method,在子類中沒有該方法,所以去父類中尋找到並調用之。
現在修改子類,重寫(override)method方法。
public class Son extends Father {
public void method() {
System.out.println("子類方法,對象類型:" + this.getClass());
}
public static void main(String[] args) {
Father sample = new Son();//向上轉型
sample.method();
}
}
結果2:
子類方法,對象類型:class samples.Son
這個結果也是意料之中的。調用method時,在子類中尋找到了該方法,所以直接調用之。
4.靜態綁定成員變量
在處理Java類中的成員變量時,並不是采用運行時綁定,而是一般意義上的靜態綁定。所以在向上轉型的情況下,對象的方法可以“找到”子類,而對象的屬性還是父類的屬性。
現在再進一步變化,在父類和子類中同時定義和賦值同名的成員變量name,並試圖輸出該變量的值。
public class Father {
protected String name="父親屬性";
public void method() {
System.out.println("父類方法,對象類型:" + this.getClass());
}
}
public class Son extends Father {
protected String name="兒子屬性";
public void method() {
System.out.println("子類方法,對象類型:" + this.getClass());
}
public static void main(String[] args) {
Father sample = new Son();//向上轉型
System.out.println("調用的成員:"+sample.name);
}
}
結果3:
調用的成員:父親屬性
這個結果表明,子類的對象(由父類的引用handle)調用到的是父類的成員變量。所以必須明確,運行時(動態)綁定針對的范疇只是對象的方法。
現在試圖調用子類的成員變量name,該怎麼做?最簡單的辦法是將該成員變量封裝成方法getter形式。
public class Father {
protected String name = "父親屬性";
public String getName() {
return name;
}
public void method() {
System.out.println("父類方法,對象類型:" + this.getClass());
}
}
public class Son extends Father {
protected String name="兒子屬性";
public String getName() {
return name;
}
public void method() {
System.out.println("子類方法,對象類型:" + this.getClass());
}
public static void main(String[] args) {
Father sample = new Son();//向上轉型
System.out.println("調用的成員:"+sample.getName());
}
}
結果4:
調用的成員:兒子屬性
本文出自 “子 孑” 博客,請務必保留此出處http://zhangjunhd.blog.51cto.com/113473/49452