Java基礎十二--多態是成員的特點 一、特點 1,成員變數。 編譯和運行都參考等號的左邊。 覆蓋只發生在函數上,和變數沒關係。 Fu f = new Zi();System.out.println(f.num);//是父類,答案是3 2,成員函數(非靜態)。 編譯看左邊,運行看右邊。 因為成員函數 ...
Java基礎十二--多態是成員的特點
一、特點
1,成員變數。
編譯和運行都參考等號的左邊。
覆蓋只發生在函數上,和變數沒關係。
Fu f = new Zi();
System.out.println(f.num);//是父類,答案是3
2,成員函數(非靜態)。
編譯看左邊,運行看右邊。
因為成員函數存在覆蓋特性。
Fu f = new Zi();//
f.show();
輸出的是子類裡面的show方法
3,靜態函數。
編譯和運行都看左邊。
靜態函數不具備多態性,多態性是對象的多態性,然後靜態函數不涉及對象。
Fu f = new Zi();//
f.show();
這裡最後輸出的是父類的show裡面的內容。
Zi z = new Zi();//
z.show();
輸出的是子類裡面的show
二、實例
1 /* 2 多態時, 3 成員的特點: 4 1,成員變數。 5 編譯時:參考引用型變數所屬的類中的是否有調用的成員變數,有,編譯通過,沒有,編譯失敗。 6 運行時:參考引用型變數所屬的類中的是否有調用的成員變數,並運行該所屬類中的成員變數。 7 簡單說:編譯和運行都參考等號的左邊。哦了。 8 作為瞭解。 9 覆蓋只發生在函數上,和變數沒關係。 10 Fu f = new Zi(); 11 System.out.println(f.num);//是父類,答案是3 12 沒根據f的值(子類對象的地址)去找,而是根據f的類型去找。 13 開發時不可能出現這樣的情況,我父類有了,我子類就直接拿來用了,而且用的時候一般都已經向下轉型了。 14 15 16 17 18 2,成員函數(非靜態)。 19 編譯時:參考引用型變數所屬的類中的是否有調用的函數。有,編譯通過,沒有,編譯失敗。 20 運行時:參考的是對象所屬的類中是否有調用的函數。 21 簡單說:編譯看左邊,運行看右邊。 22 23 因為成員函數存在覆蓋特性。 24 Fu f = new Zi();// 25 f.show(); 26 輸出的是子類裡面的show方法 27 依賴的是對象,有對象才有成員函數,必須動態的綁定到指定的對象上,所以運行的時候是看子類,而編譯的時候檢查語 28 29 法錯誤,所以編譯的時候檢查父類,所以看父類。 30 編譯檢查語法錯誤,運行時根據引用指向的地址運行。 31 32 33 34 35 3,靜態函數。 36 編譯時:參考引用型變數所屬的類中的是否有調用的靜態方法。 37 運行時:參考引用型變數所屬的類中的是否有調用的靜態方法。 38 簡單說,編譯和運行都看左邊。 39 40 其實對於靜態方法,是不需要對象的。直接用類名調用即可。 41 Fu f = new Zi();// 42 f.show(); 43 這裡最後輸出的是父類的show裡面的內容,因為靜態成員不需要對象,直接是被類名指向,都指向存靜態方法的方法區, 44 45 而那個裡面存的就是父類的show。 46 Zi z = new Zi();// 47 z.show(); 48 這裡的zi是繼承fu的,show方法是靜態的 49 輸出的是子類裡面的show 50 其實可以理解為靜態函數不具備多態性,多態性是對象的多態性,然後靜態函數不涉及對象 51 父類對象引用,就是指向父類的靜態函數 52 子類對象引用,就是指向子類的對象函數 53 54 55 56 57 */ 58 59 class Fu 60 { 61 // int num = 3; 62 void show() 63 { 64 System.out.println("fu show"); 65 } 66 67 static void method() 68 { 69 System.out.println("fu static method"); 70 } 71 } 72 73 class Zi extends Fu 74 { 75 // int num = 4; 76 void show() 77 { 78 System.out.println("zi show"); 79 } 80 81 static void method() 82 { 83 System.out.println("zi static method"); 84 } 85 } 86 87 88 89 class DuoTaiDemo3 90 { 91 public static void main(String[] args) 92 { 93 Fu.method(); 94 Zi.method(); 95 //這個的實質是父類對象指向子類引用,就是有點像指針,f的值是子類對象的地址。 96 Fu f = new Zi();// 97 // f.method();//輸出是父類的靜態 98 // f.show();//編譯的時候檢查的是父類,運行的時候以子類為主,show被覆蓋,運行的子類的show 99 //輸出是子類的show, 100 // System.out.println(f.num);//是父類,答案是3 101 102 103 // Zi z = new Zi(); 104 // System.out.println(z.num);//是子類,答案是4 105 } 106 }
三、記憶體儲存分析
Fu f = new Zi();
Fu f 在棧中定義了一個引用,也就是指針。
new Zi() 在堆中定義了一個對象,只不過這個對象有父類的那一部分成員。
1、如果用子類引用指向這個對象,全部訪問的是子類的。
2、如果用父類引用指向這個對象,全部訪問的是這個對象裡面父類的,只不過父類函數被覆蓋,所以導致成員是父類,函數時子類的。
肯定是根據指針類型去訪問要訪問的東西。貓肯定要去吃貓糧,狗才去吃狗糧。