一、什么是重寫
在子類中創建了一個與父類中名稱相同、返回值類型相同、參數列表的方法相同,只是方法體中的實現不同,以實現不同於父類的功能,這種方式被稱為方法重寫(override),又稱為方法覆蓋、方法復寫。
二、為什么需要重寫
原有的方法無法滿足新的需求,需要對這個方法進行改良來滿足新的需求。重寫是出現在子類繼承父類方法中。可以看出,重寫就是子類繼承的父類方法無法滿足子類的新的功能需求,子類對父類的這個方法進行改良重寫的一種方式。子類可以根據需要,定義特定於自己的行為。既沿襲了父類的功能名稱,又根據子類的需要重新實現父類方法,從而進行擴展增強。
三、重寫的條件/規則
- 重寫只跟非靜態方法(成員方法)有關,而與靜態方法無關:
靜態方法和非靜態方法是不一樣的:在靜態方法中,方法的調用只和左邊聲明的對象類型有關,而與右邊無關,是哪個類型,就調用對應的方法。
同時,靜態方法是在idea中無法使用快捷鍵(Alt+Insert==》選擇Overrider Methods)快速的生成重寫的方法:
非靜態方法:
非靜態方法可以由idea創建重寫的方法:
總結:
- 父類的成員方法只能被它的子類重寫。
- 聲明為 static 的方法不能被重寫,但是能夠再次聲明。
2. 方法名必須相同;
返回的類型必須與被重寫的方法的返回類型相同
參數列表必須相同;
修飾符:范圍可以擴大但不能縮小:public>Protected>Default;
拋出的異常:范圍,可以被縮小,但不能擴大;
子類的方法和父類必要一致;方法體不同!;
每種動物都有名字和年齡屬性,但是喜歡吃的食物是不同的,比如狗喜歡吃骨頭、貓喜歡吃魚等,因此每種動物的介紹方式是不一樣的。Dog通過重寫Animal的方法來表現狗特有的行為特征。
Animal父類:
public class Animal { public void shout(){ System.out.println("動物都會叫"); } void move(){ System.out.println("動物都會走"); } protected void eat(String food){ System.out.println("動物都會吃食物"); } private void breed(){ System.out.println("動物需要繁衍"); } }
Dog子類:
public class Dog extends Animal{ @Override public void shout() { System.out.println("汪汪汪"); } @Override void move() { System.out.println("狗用四只腿跑"); } @Override protected void eat(String food) { System.out.println("啃骨頭"); System.out.println("狗還要吃"+food); } }
對類進行實例化:
public class AnimalTest { public static void main(String[] args) { Animal a = new Animal(); //盡管 b 屬於 Animal 類型,但是它運行的是 Dog 類的 move方法 Animal b = new Dog(); a.shout(); a.move(); a.eat("水"); //a.breed(); 私有屬性,無法在類以外使用 b.shout(); b.move(); b.eat("肉"); } }
在上面的例子中可以看到,盡管 b 屬於 Animal 類型,但是它運行的是 Dog 類的方法。這是由於在編譯階段,只是檢查參數的引用類型。然而在運行時,Java 虛擬機(JVM)指定對象的類型並且運行該對象的方法。因此在上面的例子中,之所以能編譯成功,是因為 Animal 類中存在 move 方法,然而運行時,運行的是特定對象的方法。
以上實例編譯運行結果如下
動物都會叫 動物都會走 動物都會吃食物 汪汪汪 狗用四只腿跑 啃骨頭 狗還要吃肉
四、重寫的注意事項
- 重寫的方法可以使用 @Override 注解來標識。
- 構造方法不能被重寫。
- 聲明為 final 的方法不能被重寫。
- 子類和父類在同一個包中時,子類可以重寫父類除了聲明為 private 和 final 方法的其他方法。
- 子類和父類不在同一個包中時,子類只能重寫父類的聲明為 public 和 protected 的非 final 方法。
- 如果不能繼承一個方法,則不能重寫這個方法。重寫是在繼承的基礎上,如果方法無法被繼承那么就無法重寫
五、super關鍵字的使用
當需要在子類中調用父類的被重寫方法時,要使用 super 關鍵字。
public class Animal { public void shout(){ System.out.println("動物都會叫"); } }
子類調用父類的shout()方法:
public class Dog extends Animal{ @Override public void shout() { super.shout(); System.out.println("汪汪汪"); } }
public class AnimalTest { public static void main(String[] args) { Animal b = new Dog(); b.shout(); } }
運行結果
動物都會叫 汪汪汪