深入理解JAVA多型
何為多型,多型有什麼用,多型有什麼表現
多型是同一個行為具有多個不同表現形式或形態的能力。
比如說,你喜歡喝酒,你去酒店買酒讓服務員給你拿一瓶酒,這個時候服務員問你“要紅酒、白酒、洋酒”,這也是多型,下面給出一定程式碼演示
酒 a=new 洋酒();
酒 a=new 紅酒();
酒 a=new 白酒();
從上例就可以看出,酒有不同的形態,有不一樣的特性,這就是多型
多型的宣告
同樣用上面的例子給出解釋,例如我有一個類
class 酒{
String color;
}
以及還有幾個子類(洋酒、紅酒、白酒)派生自酒類,每個都有一個各自的特性變數price
這個時候以下宣告是合法的
酒 a=new 白酒();
然後 a.color=“白色”;這樣是沒問題的,因為你本身就是繼承與酒類,可以實現酒的方法以及變數,同時JAVA也是執行父類物件指向子類物件,但是如果你像下面這樣就是會報錯的
a.price=1000;
很多人就不明白了,明明是new的白酒類,是一個子類物件,為什麼還不能用自己的特性方法,這個時候你需要了解一下java的記憶體載入,首先是編譯看左邊,如果你父類中不存在這個變數,那麼根本通不過編譯,就別說後期的運行了。那麼,如果你問我需要執行這個變數,應該怎麼辦,這個時候就需要轉型了
向上轉型以及向下轉型
上轉型:是子類物件由父類引用,格式:parent p=new son
下轉型:是父類向下強制轉換到子類物件(前提是該父類物件必須是經過上轉型的物件)
一定注意這裡的前提,下轉型必須要經過上轉型才行,接著用上面的例子舉例
現在我們已經經過了上轉型:酒 a=new 白酒();
接下來就是下轉型:白酒 白=(白酒)a;
然後你現在白.price=1000;就可以運行了
上面的理論就這些了,下面給出兩道實際例子
提示:方法以及靜態變數是編譯看“左邊”,執行看“左邊”,變數是編譯看“左邊”,執行看“右邊”
public class demo2 { public static void main(String[] args) { 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)); } } 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 { }
輸出結果是:
A and A
A and A
A and D
B and A
B and A
A and D
B and B
B and B
A and D
關於上面程式碼的解釋如下:
1.首先我們需要明白,題目最開始我說的原則,以及,題目中有重寫方法和過載方法
(1)首先a1就是A的物件,所以直接呼叫A自身的方法,然後傳入的物件b,這個時候因為類A中沒有比配的方法,所以將物件b提升成父類a,然後找到比配的方法,輸出AA
(2)同(1),一個道理,只是提升多經歷了一步
(3)因為傳入的本身就是d物件,所以直接有比配的方法,直接列印
(4)這裡需要注意前面說的原則了,編譯看左邊,執行看右邊,所以首先去看父類中是否存在這個方法,找到了,這個show(A obj)方法,然而這個方法被B類重寫,所以執行B類的show(A obj)列印BA
(5)這裡存在一個問題,按道理執行看右邊,然後將C物件提升,列印應該是BB,然而結果卻是BA,這裡我們需要注意,編譯是看的左邊,如果類A都不存在這個方法,那麼編譯就直接報錯,所以,這個時候一樣是在類A裡面找,找到了show(A obj)方法,然後被重寫,所以列印BA
(6)同(5)一個道理,也是首先在類A裡面找到,然後有一個直接比配show(D obj)就可以直接列印AD
(7)(8)就很簡單了,本身就是類B的物件,所以直接在類B中尋找,然後找到了,就列印BB
(9)這裡需要注意,雖然是類B的物件,但是B是繼承的A類,所以A類的方法也可以使用,所以會比配到A類的show(D obj)列印AD
好了,這就是這個題的解釋,或許還有其他人的解釋和我不一樣,
以下我會給出我的總結
1.方法以及靜態變數是編譯看“左邊”,執行看“左邊”,變數是編譯看“左邊”,執行看“右邊”
2.有多型,先看父類方法是否存在,或者可以經過提升轉換,然後再看子類的重寫
3.繼承鏈中物件方法的呼叫存在一個優先順序:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。