以前JAVA看的少,最近做項目,對@Override的調用順序有點疑惑,故查了一些資料。既然查資料了,那就把能看到的知識點整理一下,以供日后學習。
原文地址請保留http://www.cnblogs.com/rossoneri/p/3977038.html
關於重寫
當一個子類繼承一父類,而子類中的方法與父類中的方法的名稱,參數個數、類型都完全一致時,就稱子類中的這個方法重寫了父類中的方法。通常,派生類繼承基類的方法,因此,在調用對象繼承方法的時候,調用和執行的是基類的實現.但是,有時需要對派生類中的繼承方法有不同的實現.
例如,假設動物類存在"跑"的方法,從中派生出馬和狗,馬和狗的跑得形態是各不相同的,因此同樣方法需要兩種不同的實現,這就需要"重新編寫"基類中的方法。"重寫"基類方法就是修改它的實現或者說在派生類中重新編寫。
重寫是子類與父類的一種多態性體現。
重寫允許子類改變父類的一些行為,當父類不滿足子類的一些要求時我們就需要子類對父類的一些行為進行重寫。
重寫示例
例如:某公司里的員工的電話號碼不允許對外公開,而銷售人員(員工)的電話號碼則需要對外公開。
1 public class Employee { 2 3 private String mobile; 4 5 public Employee(String mobile) { 6 this.mobile = mobile; 7 } 8 9 protected String showMess(){ 10 return "電話號碼:"+mobile; 11 } 12 }
員工類的showMess方法是protected的,所以位於其他包的對象是訪問不到的。
然后定義一個銷售人員的類(Sales),並繼承Employee類
1 public class Sales extends Employee{ 2 3 //子類除了具有父類的一些屬性,也可以有自己的一些屬性 4 private String msn; 5 6 public Sales(String mobile,String msn) { 7 super(mobile); 8 this.msn = msn; 9 } 10 11 @Override 12 public String showMess() { 13 return super.showMess()+"==msn:"+this.msn; 14 } 15 }
注意這時被覆蓋的showMess方法的訪問級別是public,可以被任何其他對象訪問到。
關鍵點
1.被覆蓋方法的訪問控制級別可以不一樣。
例如上例父類的showMess方法的訪問級別為protected的,而子類覆蓋的showMess方法訪問級別則為public的。
但子類的訪問級別必須要高於父類被覆蓋方法的訪問級別,如果父類是public的而子類是protected的則是錯誤的。
2.方法被定義為private或static或final的則不能被覆蓋。
3.方法的返回類型。
前面說了,重寫的方法名稱,參數及類型必須一致,但沒有提返回類型。這里,返回類型可以不一樣,但類型有限制。
子類的返回類型可以是更具體的對象,例如可以將Employee類的返回類型改為Object也正確。而倒過來則錯誤。
4.在方法調用時先會在子類中找覆蓋的方法,如果子類中沒有則會在父類中去找。
調用順序示例
1 public class Parent { 2 3 private int num(int i,int j){ 4 return i+j; 5 } 6 7 public static void main(String[] args) { 8 Parent p = new Child(); 9 System.out.println(p.num(1, 2)); 10 } 11 } 12 class Child extends Parent{ 13 14 public int num(int x,int y){ 15 return x-y; 16 } 17 }
這段代碼的執行結果為什么呢?如果你回答-1則錯了,正確答案是3。
為什么呢?因為父類的num方法是private的,所以不能被覆蓋,所以子類的num方法不是一種Override,因此在子類找不到被覆蓋的num方法就會執行父類的num方法。所以結果輸出為3.如果把private改為protected或者public結果就是-1了
1 public class Parent { 2 3 public int test(){ 4 //執行子類的num方法 5 return num(1,2); 6 } 7 8 protected int num(int i,int j){ 9 return i+j; 10 } 11 12 public static void main(String[] args) { 13 Parent p = new Child(); 14 System.out.println(p.test()); 15 } 16 17 } 18 class Child extends Parent{ 19 20 public int num(int x,int y){ 21 return x-y; 22 } 23 }
那么這段代碼的執行結果是-1,因為父類test方法調用的是子類的num方法。
再看下一個例子,先寫一個基類:
1 package tttttest; 2 3 public class Fruit { 4 public void show_name(int num) { 5 System.out.println("Fruit: " + num); 6 } 7 8 public static void main(String[] args) { 9 // TODO code application logic here 10 Fruit apple = new Apple(); 11 apple.show_name(2); 12 } 13 }
之后我們編寫一個Apple子類,繼承這個基類。並且復寫基類中的show_name()方法。
1 package tttttest; 2 3 public class Apple extends Fruit{ 4 5 @Override 6 public void show_name(int num) { 7 // TODO Auto-generated method stub 8 System.out.println("Apple: " + num); 9 } 10 11 }
輸出結果就是Apple: 2
關於@Override標簽
@Override是偽代碼,表示重寫
一來可以當作注釋來看
二來增加代碼的可讀性,看到標簽就知道這是從父類重寫的方法
三來,就是IDE會根據這個標簽來檢查你的代碼。如果你寫代碼的時候不太注意重寫規范,犯了上面寫的4個關鍵點的錯誤還沒發現,你若加上這個標簽,IDE便會幫你標記錯誤。
怎么讓IDE自動加@Override標簽
我用Eclipse的添加方法是:在editor中單擊鼠標右鍵->Source->Override/Implement Methods
在列表中選擇需要重寫的方法即可。
參考資料
分享一下@Override標簽背后的小秘密---記錄java的思行合一