多態(tài)是面向?qū)ο蟪绦蛟O(shè)計(jì)中代碼重用的一個(gè)重要機(jī)制村砂,它表示當(dāng)同一個(gè)操作作用在不同對(duì)象時(shí)保屯,會(huì)有不同的語義辜膝,從而產(chǎn)生不同的結(jié)果。在java語言中飞蛹,多態(tài)主要有以下兩種表現(xiàn)方式:
1.方法的重載(overload)谤狡。重載是指同一個(gè)類中有多個(gè)同名的方法,但這些方法有著不同的參數(shù)桩皿,因此在編譯時(shí)就可以確定到底調(diào)用哪個(gè)方法豌汇,它是一種編譯時(shí)多態(tài)幢炸。重載可以被看做一個(gè)類中的方法多態(tài)性泄隔。
2.方法的覆蓋(override)。子類可以覆蓋父類的方法宛徊,因此同樣的方法會(huì)在父類與子類中有著不同的表現(xiàn)形式佛嬉。在java語言中,基類的引用變量不僅可以指向基類的實(shí)例對(duì)象闸天,也可以指向其子類的實(shí)例對(duì)象暖呕。同樣,接口的引用變量也可以指向其實(shí)現(xiàn)類的實(shí)例對(duì)象苞氮。而程序調(diào)用的方法在運(yùn)行期才動(dòng)態(tài)綁定(綁定指的是將一個(gè)方法調(diào)用和一個(gè)方法主體連接到一起)湾揽,就是引用變量所指向的具體實(shí)例對(duì)象的方法,也就是內(nèi)存里正在運(yùn)行的那個(gè)對(duì)象的方法笼吟,而不是引用變量的類型中定義的方法库物。通過這張動(dòng)態(tài)綁定的方法實(shí)現(xiàn)了多態(tài)。由于只有在運(yùn)行時(shí)才能確定調(diào)用哪個(gè)方法贷帮,戚揭,因此通過方法覆蓋實(shí)現(xiàn)的多態(tài)也可以稱為運(yùn)行時(shí)多態(tài),示例如下:
public class Test{
public static void main(String[] args){
Base b = new Derived();
b.f();
b.g();
}
}
class Base {
public Base(){
g();
}
public void f(){
System.out.println("Base f()");
}
public void g(){
System.out.println("Base g()");
}
}
class Derived extends Base{
public void f(){
System.out.println("Derived f()");
}
public void g(){
System.out.println("Derived g()");
}
}
運(yùn)行結(jié)果為:
Derived g()
Derived f()
Derived g()
在上例中,子類Derived的f()方法和g()方法會(huì)覆蓋父類Base的f()方法和g()方法撵枢。在執(zhí)行Base b = new Derived()語句時(shí)民晒,對(duì)象b雖然被聲明為Base,但是對(duì)象b的引用為Derived的一個(gè)實(shí)例化對(duì)象锄禽。即對(duì)象b存儲(chǔ)在棧內(nèi)存潜必,對(duì)象b的引用存儲(chǔ)在堆內(nèi)存,其在棧內(nèi)存中存儲(chǔ)的值為堆內(nèi)存的地址沃但,訪問對(duì)象b即訪問一個(gè)實(shí)例化的Derived對(duì)象刮便。Derived實(shí)例化時(shí)會(huì)默認(rèn)調(diào)用父類Base的無參構(gòu)造方法,此構(gòu)造方法會(huì)調(diào)用子類的g()方法绽慈,而非父類的g()方法恨旱,因此會(huì)輸出Derived g()辈毯。由于實(shí)際創(chuàng)建的是Derived類的對(duì)象,后面的方法調(diào)用都會(huì)調(diào)用子類Derived的方法搜贤。