這是我參與8月更文挑戰的第8天,活動詳情查看:8月更文挑戰web
上篇說到Java繼承的定義使用 今天來了解下Java中的方法覆蓋,經過這篇文章讓你們理解在什麼狀況下咱們須要進行方法覆蓋,以及掌握在知足什麼條件的時候構成方法覆蓋。markdown
學習方法覆蓋以前,咱們先來回顧一下方法重載(overload),什麼狀況下考慮使用方法重載呢?ide
在同一個類當中,若是功能類似,儘量將方法名定義的相同,這樣方便調用的同時代碼也會美觀。oop
那麼,代碼知足什麼條件的時候可以構成方法重載呢?post
只要在同一個類當中,方法名相同,參數列表不一樣(類型、個數、順序),即構成方法重載。學習
方法重載發生在同一個類當中。this
方法覆蓋是發生在具備繼承關係的父子類之間。url
方法重載是一個類中,方法名相同,參數列表不一樣。spa
方法覆蓋是具備繼承關係的父子類,而且重寫以後的方法必須和以前的方法一致:方法名一致、參數列表一致、返回值類型一致。3d
帶着一樣的疑問往下看,開始去學習方法覆蓋,什麼是方法覆蓋?什麼狀況下考慮方法覆蓋?代碼怎麼寫的時候就構成了方法覆蓋呢?
接下來看一段代碼:
public class People {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void speakHi(){
System.out.println(this.name + "和別人打招呼!");
}
}
複製代碼
public class ChinaPeople extends People {
//中國人
}
複製代碼
public class AmericaPeople extends People {
//美國人
}
複製代碼
public class PeopleTest {
public static void main(String[] args) {
ChinaPeople cp = new ChinaPeople();
cp.setName("張三");
cp.speakHi();
AmericaPeople ap = new AmericaPeople();
ap.setName("jackson");
ap.speakHi();
}
}
複製代碼
運行結果以下圖所示:
「中國人」調用speakHi()
方法但願輸出的結果是「你好,我叫張三,很高興見到你!」,「美國人」調用speakHi()
方法更但願輸出的結果是「Hi,My name is jackson,Nice to meet you!」,可見ChinaPeople
和AmericaPeople
從父類中繼承過來的speakHi()方法已經不夠子類使用了,那這個時候應該怎麼辦呢?
固然,此時就須要使用方法覆蓋機制了。請看如下代碼:
public class People {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void speakHi(){
System.out.println(this.name + "和別人打招呼!");
}
}
複製代碼
public class ChinaPeople extends People {
public void speakHi(){
System.out.println("你好,我叫"+this.getName()+",很高興認識你!");
}
}
複製代碼
public class AmericaPeople extends People {
public void speakHi(){
System.out.println("Hi,My name is "+this.getName()+",Nice to meet you!");
}
}
複製代碼
public class PeopleTest {
public static void main(String[] args) {
ChinaPeople cp = new ChinaPeople();
cp.setName("張三");
cp.speakHi();
AmericaPeople ap = new AmericaPeople();
ap.setName("jackson");
ap.speakHi();
}
}
複製代碼
運行結果以下圖所示:
以上程序中ChinaPeople和AmericaPeople將從People類中繼承過來的speakHi()
方法進行了覆蓋,咱們也看到了當speakHi()
方法發生覆蓋以後,子類對象會調用覆蓋以後的方法,不會再去調用以前從父類中繼承過來的方法。
那麼,到底在什麼狀況下咱們會考慮使用方法覆蓋呢?
經過以上內容的學習,咱們瞭解到只有當從父類中繼承過來的方法沒法知足當前子類業務需求的時候,須要將父類中繼承過來的方法進行覆蓋。
換句話說,父類中繼承過來的方法已經不夠用了,子類有必要將這個方法從新再寫一遍,因此方法覆蓋又被稱爲方法重寫。當該方法被重寫以後,子類對象必定會調用重寫以後的方法。
那麼,當程序具有哪些條件的時候,就能構成方法覆蓋呢?
● 方法覆蓋發生在具備繼承關係的父子類之間,這是首要條件;
● 覆蓋以後的方法與原方法具備相同的返回值類型、相同的方法名、相同的形式參數列表;
另外,在使用方法覆蓋的時候,須要有哪些注意事項呢?
● 因爲覆蓋以後的方法與原方法如出一轍,建議在開發的時候採用複製粘貼的方式,不建議手寫,由於手寫的時候很是容易出錯,好比在Object類當中有toString()方法,該方法中的S是大寫的,在手寫的時候很容易寫成小寫tostring(),這個時候你會認爲toString()方法已經被覆蓋了,但因爲方法名不一致,致使最終沒有覆蓋,這樣就尷尬了;
● 私有的方法不能被繼承,因此不能被覆蓋;
● 構造方法不能被繼承,因此也不能被覆蓋;
● 覆蓋以後的方法不能比原方法擁有更低的訪問權限,能夠更高(學習了訪問控制權限修飾符以後你就明白了);
● 覆蓋以後的方法不能比原方法拋出更多的異常,能夠相同或更少(學習了異常以後就明白了);
● 方法覆蓋只是和方法有關,和屬性無關;
● 靜態方法不存在覆蓋(不是靜態方法不能覆蓋,是靜態方法覆蓋意義不大,學習了多態機制以後就明白了);
以上的注意事項還須要記憶,多下點功夫吧。
接下來咱們再來看一段代碼,對方法覆蓋加深一下印象,業務需求是這樣的:定義一個動物類,全部動物都有移動的行爲,其中貓類型的對象在移動的時候輸出「貓在走貓步!」,鳥兒類型的對象在移動的時候輸出「鳥兒在飛翔!」,可是貓類型的對象具備一個特殊的行爲,抓老鼠,這個行爲不是全部動物對象都有的,是貓類型對象特有的:
public class Animal {
public void move(){
System.out.println("動物在移動!");
}
}
複製代碼
public class Cat extends Animal{
public void move(){
System.out.println("貓在走貓步!");
}
public void catchMouse(){
System.out.println("貓抓老鼠!");
}
}
複製代碼
public class Bird extends Animal{
public void move(){
System.out.println("鳥兒在飛翔!");
}
}
複製代碼
public class Test {
public static void main(String[] args) {
Cat cat = new Cat();
cat.move();
cat.catchMouse();
Bird bird = new Bird();
bird.move();
}
}
複製代碼
運行結果以下圖所示:
對方法覆蓋總結一下,當父類中繼承過來的方法沒法知足當前子類業務需求的時候,子類有必要將父類中繼承過來的方法進行覆蓋/重寫。方法覆蓋發生在具備繼承關係的父子類之間,方法覆蓋的時候要求相同的返回值類型、相同的方法名、相同的形式參數列表。方法覆蓋以後子類對象在調用的時候必定會執行覆蓋以後的方法。