關於java多型

劍握在手發表於2013-11-08

多型有一種情況是,父類應用指向子類物件:

父親 fu = new 兒子();

這個時候如果父親中有變數(包括靜態和非靜態變數)或者靜態方法,都不會被兒子覆蓋和重寫。他們在記憶體中佔用的是兩塊地方。

而非靜態方法則會被重寫。

 

記憶體中該物件的內容:

            父類的成員變數  ①  

                 父類的靜態方法  ①

            子類的成員變數 ②

            子類的靜態方法 ②

            父類中未被重寫的非靜態方法 ③ 

            父類中被子類重寫的非靜態方法 ③          

                                  子類自己新寫的方法 ④

當引用是父型別的時候指向 ① ③

當引用是子型別的時候指向 ② ③ ④

 

引用的型別被強制轉換的過程中記憶體中的資料都是同一組資料。

 

所以我們常用的方式是private 屬性 加 get set方法方式,這樣對大部分人來說不會太亂。

 

參考測試程式碼如下:

class Fu{
 static int fu = 0;
 int zi = 0;
 public void me(){
  System.out.println("Wo Shi Fu");
 }
 public static void staticMethod(){
  System.out.println("Fu de static method");
 }
}

class Zi extends Fu{
 static int fu = 1;
 int zi = 1;
 public void me(){
  System.out.println("Wo Shi Zi");
 }
 public static void staticMethod(){
  System.out.println("Zi de static method");
 }
}

public class Test2 {
 public static void main(String[] args) {
  Fu x = new Zi();
  System.out.println(x.fu);
  System.out.println(x.zi);
  x.me();
  x.staticMethod();
  System.out.println("-------------華麗的分割線------------------");  
  //如果這個時候改變x中的變數
  
  x.fu=99;
  x.zi=99;
  
  //強制轉換成子物件
  Zi y = (Zi)x;
  System.out.println("-------------強制轉換成子類型別後的內容------------------"); 
  System.out.println(y.fu);
  System.out.println(y.zi);
  y.me();
  y.staticMethod();
  System.out.println("-------------華麗的分割線------------------"); 
  
  y.fu = 88;
  y.zi = 88;
  
  System.out.println("-------------強制轉換成子類型別後----再次強制轉換為父類型別的內容------------------"); 
  Fu a = (Fu)y;
  System.out.println(a.fu);
  System.out.println(a.zi);
  a.me();
  a.staticMethod();
  

  System.out.println("-------------強制轉換成子類型別後----再次強制轉換為父類型別的內容------------------"); 
  Zi b = (Zi)a;
  System.out.println(b.fu);
  System.out.println(b.zi);
  b.me();
  b.staticMethod();
  
 }

}

 

輸出:

0
0
Wo Shi Zi
Fu de static method
-------------華麗的分割線------------------
-------------強制轉換成子類型別後的內容------------------
1
1
Wo Shi Zi
Zi de static method
-------------華麗的分割線------------------
-------------強制轉換成子類型別後----再次強制轉換為父類型別的內容------------------
99
99
Wo Shi Zi
Fu de static method
-------------強制轉換成子類型別後----再次強制轉換為父類型別的內容------------------
88
88
Wo Shi Zi
Zi de static method

以上僅代表個人觀點,奉勸大家盡信書不如無書,書也是人寫的。

 

 

 

附:

多型關於反射的擴充:

 

package test.test;

import java.lang.reflect.Method;

public class Test2 {
 
    public static void main(String[] args) throws Exception {
        test(new hi());
}
     
 
    public static void test(Object obj) throws Exception {
        System.out.println(obj);
        Object object = hi.class.newInstance();
        Method mtd = hi.class.getDeclaredMethod("print", null);
        mtd.setAccessible(true);
        mtd.invoke(object, null);
    }
}
 
class hi{
    public String toString() {
        return "hi";
    }
    private void print() {
        System.out.println("invokeOk");
    }
}

 

 

輸出結果:

hi
invokeOk

 

呼叫test方法時,傳入引數相當於Object obj = new hi();

這個時候記憶體中是有print方法的,雖然obj沒有指向這個方法。

當用反射呼叫某個物件的某個方法時的時候,反射技術不會關心這個物件的引用有沒有指向指向這個方法,而是關心這個物件所指向的記憶體中有沒有這個方法。

 

相關文章