JAVA過載(overload)和覆蓋(override)中你所不知道的陷阱

瓜瓜東西發表於2014-05-26

大家都知道過載是指在同一個類中,定義了有相同名稱但是有不同引數型別的方法時,到底呼叫那一個方法會根據引數型別來選擇.我們來看下面這個例子:

  1. public class ParentClass {  
  2.   
  3. }  
  4. public class ChildClass extends ParentClass{  
  5.   
  6. }  
  7. public class Test {  
  8.     public void testOverLoad(ParentClass cls){  
  9.         System.out.println("It's ParentClass");  
  10.     }  
  11.     public void testOverLoad(ChildClass cls){  
  12.         System.out.println("It's ChildClass");  
  13.     }  
  14.     public static void main(String[] args) {  
  15.         Test test = new Test();  
  16.         ParentClass parentCls = new ParentClass();  
  17.         ParentClass childCls = new ChildClass();  
  18.           
  19.         test.testOverLoad(parentCls);  
  20.         test.testOverLoad(childCls);  
  21.     }  
  22. }  

大家想想輸出的結果應該是什麼呢,答案是: 
It's ParentClass 
It's ParentClass 
原因是決定方法過載是在編譯的時候發生,而不是在執行的時候. 
覆蓋是指在父類和子類有相同名稱引數的方法,子類的方法覆蓋父類的方法.來看下面的例子:

  1. public class ParentClass {  
  2.     public String str1 = "Parent1";  
  3.     public String str2 = "";  
  4.     public  ParentClass(){  
  5.         str2="Parent2";  
  6.     }  
  7.     public void func(){  
  8.         System.out.println("ParentClass.func");  
  9.     }  
  10.     public String getStr2() {  
  11.         return str2;  
  12.     }  
  13. }  
  14. public class ChildClass extends ParentClass{  
  15.     public String str1 = "Child1";  
  16.     public String str2 = "";      
  17.     public  ChildClass(){  
  18.         str2="Child2";  
  19.     }  
  20.       
  21.     public void func(){  
  22.         System.out.println("ChildClass.func");  
  23.     }  
  24.   
  25.     public String getStr2() {  
  26.         return str2;  
  27.     }  
  28.   
  29. }  
  30. public class Test   
  31.     public static void main(String[] args) {  
  32.         ParentClass childCls = new ChildClass();  
  33.   
  34.         System.out.println(childCls.str1);  
  35.         System.out.println(childCls.str2);  
  36.         System.out.println(childCls.getStr2());  
  37.         childCls.func();  
  38.     }  
  39. }  

輸出的結果應該是什麼呢,答案是: 
Parent1 
Parent2 
Child2 
ChildClass.func 
原因是對於方法的覆蓋發生在執行時,所以子類的方法被呼叫.而對於變數的覆蓋是在編譯的時候決定的,childCls在編譯的時候型別是ParentClass,所以對變數的直接訪問得到的是ParentClass中定義的值.對於成員變數,編譯器會對父類和子類的所有成員變數都儲存一份拷貝.

相關文章