多態成員變量的特點:
1 class DuotaiTest2 2 { 3 public static void main(String[] args) 4 { 5 A a = new A(); 6 A b1 = new B(); 7 B b2 = new B(); 8 System.out.println(a.name); 9 System.out.println(a.a); 10 System.out.println(b1.name); 11 System.out.println(b1.a);//子類向上轉型成父類,再調用子類特有成員變量,編譯報錯 12 System.out.println(((B)b1).name); 13 System.out.println(((B)b1).b); 14 System.out.println(b2.name); 15 System.out.println(b2.b); 16 } 17 } 18 19 class A 20 { 21 String name = "A";//父子類同名變量 22 int a = 1;//父類特有變量 23 } 24 25 class B extends A 26 { 27 String name = "B"; 28 int b = 2;//子類特有變量 29 } 30 31 /* 32 總結: 33 調用成員變量時, 類變量.成員變量 語句在執行時依據類變量類型進行選擇入口 34 */
運行結果:
圖解:
java中,子類的實例對象在堆內存中的存放應如圖所示,既有子類的成員變量,又有父類的成員變量;
同一對象可以有多態,當父類變量指向時,從A入口進入,可以訪問父類的所有成員變量;當子類變量指向時,從B入口進入,可以訪問子類的所有成員變量和父類非同名變量;
總結: 調用成員變量時, 類變量.成員變量 語句在執行時依據類變量類型進行選擇入口
多態(非靜態)成員函數的特點:
我寫了一個“重寫”過程的思想本質,那個可以解釋多態(非靜態)成員函數的特點原理。
圖解:
java中,實例對象即使被向上轉型成父類,其實其在內存中的存儲形式依舊是子類實例對象(轉型...有講),基於這個結論就好解釋了
多態是將子類實例對象向上轉型後賦給父類變量,其在內存中依舊是子類實例對象,在通過該變量調用方法時,JVM會通過判斷該變量指向的實例對象在內存的形式來確定進入方法區的那塊去尋找方法
因為轉型後類型不變,所以JVM還是進入Child的方法區尋找方法,而Child自己定義了show()方法,所以調用了子類的show()
總結:
(非靜態)成員函數的訪問原則是通過判斷調用對象在內存中的形式而進行的,是子類實例則運行子類方法,是父類示例則運行父類方法,與變量類型無關
多態靜態方法的特點:
1 /* 2 需求:設計一個簡單的java程序,確定多態中靜態方法的訪問特點 3 思路:設計一對子父類,創建子類實例,子類變量和父類變量同時指向該實例,通過不同變量調用查看結果 4 */ 5 class DuotaiTest3 6 { 7 public static void main(String[] args) 8 { 9 Child c = new Child(); 10 Father f = c; 11 c.show(); 12 f.show(); 13 } 14 } 15 16 class Father 17 { 18 static void show(){ 19 System.out.println("Father show run."); 20 } 21 } 22 23 class Child extends Father 24 { 25 static void show(){ 26 System.out.println("Child show run."); 27 } 28 } 29 30 /* 31 總結: 32 同一個實例對象,不同類型的變量指向,通過不同變量調用會得到不同的結果表明: 33 靜態方法調用的判斷是依據調用者的變量類型而進行的。 34 類變量.方法 語句中,類變量類型決定著JVM在靜態方法區的入口選擇 35 */
總結: 同一個實例對象,不同類型的變量指向,通過不同變量調用會得到不同的結果表明: 靜態方法調用的判斷是依據調用者的變量類型而進行的。 類變量.方法 語句中,類變量類型決定著JVM在靜態方法區的入口選擇