http://blog.sina.com.cn/s/blog_59c9412d0100g7is.html
運行時綁定也叫動態綁定,它是一種調用對象方法的機制。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:
調用的成員:兒子屬性