深入理解java多態(tài)性 昨天看到一個關(guān)于多態(tài)性的帖子,,參考了回帖者的理解,加入了一些自己的看法,,整理出來供大家參考,,不一定完全正確,歡迎大家批評指正,。 (一)相關(guān)類 class A ...{ public String show(D obj)...{ return ("A and D"); } public String show(A obj)...{ return ("A and A"); } } class B extends A...{ public String show(B obj)...{ return ("B and B"); } public String show(A obj)...{ return ("B and A"); } } class C extends B...{} class D extends B...{} (二)問題:以下輸出結(jié)果是什么,? A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println(a1.show(b)); ① System.out.println(a1.show(c)); ② System.out.println(a1.show(d)); ③ System.out.println(a2.show(b)); ④ System.out.println(a2.show(c)); ⑤ System.out.println(a2.show(d)); ⑥ System.out.println(b.show(b)); ⑦ System.out.println(b.show(c)); ⑧ System.out.println(b.show(d)); ⑨ (三)答案 ① A and A (四)分析 ①②③比較好理解,一般不會出錯,。④⑤就有點糊涂了,,為什么輸出的不是"B and B”呢???!先來回顧一下多態(tài)性。 運行時多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計代碼重用的一個最強大機制,,動態(tài)性的概念也可以被說成“一個接口,,多個方法”。Java實現(xiàn)運行時多態(tài)性的基礎(chǔ)是動態(tài)方法調(diào)度,,它是一種在運行時而不是在編譯期調(diào)用重載方法的機制,。 方法的重寫Overriding和重載Overloading是Java多態(tài)性的不同表現(xiàn)。重寫Overriding是父類與子類之間多態(tài)性的一種表現(xiàn),重載Overloading是一個類中多態(tài)性的一種表現(xiàn),。如果在子類中定義某方法與其父類有相同的名稱和參數(shù),,我們說該方法被重寫(Overriding)。子類的對象使用這個方法時,,將調(diào)用子類中的定義,,對它而言,父類中的定義如同被“屏蔽”了,。如果在一個類中定義了多個同名的方法,它們或有不同的參數(shù)個數(shù)或有不同的參數(shù)類型,,則稱為方法的重載(Overloading),。Overloaded的方法是可以改變返回值的類型。 當超類對象引用變量引用子類對象時,,被引用對象的類型而不是引用變量的類型決定了調(diào)用誰的成員方法,,但是這個被調(diào)用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法,。 (但是如果強制把超類轉(zhuǎn)換成子類的話,,就可以調(diào)用子類中新添加而超類沒有的方法了。) 好了,,先溫習到這里,,言歸正傳!實際上這里涉及方法調(diào)用的優(yōu)先問題 ,,優(yōu)先級由高到低依次為:this.show(O),、super.show(O)、this.show((super)O),、super.show((super)O),。讓我們來看看它是怎么工作的。 比如④,,a2.show(b),,a2是一個引用變量,類型為A,,則this為a2,,b是B的一個實例,于是它到類A里面找show(B obj)方法,,沒有找到,,于是到A的super(超類)找,而A沒有超類,,因此轉(zhuǎn)到第三優(yōu)先級this.show((super)O),,this仍然是a2,這里O為B,(super)O即(super)B即A,,因此它到類A里面找show(A obj)的方法,,類A有這個方法,但是由于a2引用的是類B的一個對象,,B覆蓋了A的show(A obj)方法,,因此最終鎖定到類B的show(A obj),輸出為"B and A”,。 再比如⑧,,b.show(c),b是一個引用變量,,類型為B,,則this為b,c是C的一個實例,,于是它到類B找show(C obj)方法,,沒有找到,轉(zhuǎn)而到B的超類A里面找,,A里面也沒有,,因此也轉(zhuǎn)到第三優(yōu)先級this.show((super)O),this為b,,O為C,,(super)O即(super)C即B,因此它到B里面找show(B obj)方法,,找到了,,由于b引用的是類B的一個對象,因此直接鎖定到類B的show(B obj),,輸出為"B and B”,。 按照上面的方法,可以正確得到其他的結(jié)果,。 問題還要繼續(xù),,現(xiàn)在我們再來看上面的分析過程是怎么體現(xiàn)出藍色字體那句話的內(nèi)涵的。它說:當超類對象引用變量引用子類對象時,,被引用對象的類型而不是引用變量的類型決定了調(diào)用誰的成員方法,,但是這個被調(diào)用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法,。還是拿a2.show(b)來說吧,。 a2是一個引用變量,類型為A,,它引用的是B的一個對象,,因此這句話的意思是由B來決定調(diào)用的是哪個方法,。因此應(yīng)該調(diào)用B的show(B obj)從而輸出"B and B”才對。但是為什么跟前面的分析得到的結(jié)果不相符呢,?,!問題在于我們不要忽略了藍色字體的后半部分,那里特別指明:這個被調(diào)用的方法必須是在超類中定義過的,,也就是被子類覆蓋的方法,。B里面的show(B obj)在超類A中有定義嗎?沒有,!那就更談不上被覆蓋了,。實際上這句話隱藏了一條信息:它仍然是按照方法調(diào)用的優(yōu)先級來確定的。它在類A中找到了show(A obj),,如果子類B沒有覆蓋show(A obj)方法,,那么它就調(diào)用A的show(A obj)(由于B繼承A,雖然沒有覆蓋這個方法,,但從超類A那里繼承了這個方法,從某種意義上說,,還是由B確定調(diào)用的方法,,只是方法是在A中實現(xiàn)而已);現(xiàn)在子類B覆蓋了show(A obj),,因此它最終鎖定到B的show(A obj),。這就是那句話的意義所在。 |
|