前言
上班時間,正在互聯(lián)網(wǎng)暢游中
忽然發(fā)現(xiàn)網(wǎng)頁中出現(xiàn)了個名詞 “java的動態(tài)綁定”, 頓感疑惑, 于是問了周邊的同事
同事們商量好了一樣, 統(tǒng)一回復(fù) “沒聽過”!
求知欲爆棚的咸魚君只能自己研究
概念
什么叫綁定?
常識中, 綁定就是產(chǎn)生關(guān)聯(lián)的意思, 程序的世界也差不多是這個意思.
不妨換個問題
當(dāng)你想調(diào)用某個類的某個方法時, Java如何知道這個類和這個方法之間的關(guān)系的?
這就主要?dú)w功于Java的綁定機(jī)制了.
在Java中, 綁定分為兩種
靜態(tài)綁定(前期綁定)
動態(tài)綁定(后期綁定)
靜態(tài)綁定
在程序執(zhí)行前,方法已經(jīng)被綁定, 靜態(tài)綁定發(fā)生在編譯時期,也就是在編譯的時候我們就知道這個方法和類之間的關(guān)系.
在Java中, private static 和 final 方法都是靜態(tài)綁定.
動態(tài)綁定
Java是一門面向?qū)ο蟮木幊陶Z言, 優(yōu)勢就在于支持多態(tài).
多態(tài)的概念我們一句話解釋下: 子類繼承了父類, 并重寫了父類的方法.
多態(tài)的特性而引起了一個問題:
class Parent {
void say() {
System.out.println("Parent.say()");
}
void run() {
System.out.println("Parent.run()");
}
}
class Child extends Parent {
void say() {
System.out.println("Child.say()");
}
}
//父類引用指向子類對象, 向上轉(zhuǎn)型
Parent p = new Child();
p.say();
p.run();
此時p.say();p.run();輸出啥?
理論上講, p是個Parent對象, 那應(yīng)該是調(diào)用Parent的say()和run();
但是實(shí)際上我們期待的結(jié)果是調(diào)用Child對象的say()和run();
于是引出了動態(tài)綁定的概念
調(diào)用子類型對象的一個虛方法(非private,final or static), 編譯器將無法找到真正需要調(diào)用的方法, 因?yàn)樗赡苁嵌x在父類型中的方法,也可能是在子類型中被重寫的方法.
這種情形,只能在運(yùn)行時進(jìn)行解析,因?yàn)橹挥性谶\(yùn)行時期,才能明確具體的對象到底是什么.
動態(tài)綁定體現(xiàn)了Java的繼承與多態(tài),在繼承鏈中,JVM一直沿著繼承鏈動態(tài)找到帶有該方法的實(shí)現(xiàn).
不難看出, 最終輸出結(jié)果是
Child.say() //子類重寫
Parent.run() //子類未重寫, 根據(jù)繼承鏈找到了父類實(shí)現(xiàn)
注意點(diǎn)
理解了動態(tài)綁定的概念, 我們繼續(xù)拓展,下面這段代碼輸出啥
class Parent {
int age = 60;
}
class Child extends Parent {
int age = 20;
}
Parent p = new Child();
System.out.println("age = " + p.age);
此時輸出的age是Child對象的還是Parent對象的?
我們的期望肯定是輸出Child對象的20
但實(shí)際
age = 60
為什么呢? 說好的動態(tài)綁定呢?!
這就得強(qiáng)調(diào)下動態(tài)綁定的第二個特性了
- 當(dāng)調(diào)用對象方法的時候,該方法會和該對象的內(nèi)存地址/運(yùn)行類型(也就是與運(yùn)行類型)綁定
當(dāng)調(diào)用對象屬性時,沒有動態(tài)綁定機(jī)制,哪里聲明,哪里使用
看到這里, 動態(tài)綁定算是理解了.
不妨結(jié)合下面這段代碼來加深下理解
class Parent {
int age = 60;
int getAge() {
return age;
}
}
class Child extends Parent {
int age = 20;
int getAge() {
return age;
}
}
Parent p = new Child();
System.out.println("age = " + p.age);
System.out.println("age = " + p.getAge());
請關(guān)注我的訂閱號
