重寫方法不能比被重寫方法限制有更嚴格的訪問級別。
(但是可以更廣泛,比如父類方法是包訪問權限,子類的重寫方法是public訪問權限。) 比如:Object類有個toString()方法,開始重寫這個方法的時候我們總容易忘記public修飾符,編譯器當然不會放過任何教訓我們 的機會。出錯的原因就是:沒有加任何訪問修飾符的方法具有包訪問權限,包訪問權限比public當然要嚴格了,所以編譯器會報錯的。
B、重寫規則之二:
參數列表必須與被重寫方法的相同。
重寫有個孿生的弟弟叫重載,也就是後面要出場的。如果子類方法的參數與父類對應的方法不同,那麼就是你認錯人了,那是重載,不是重寫。
C、重寫規則之三:
返回類型必須與被重寫方法的返回類型相同。
父類方法A:void eat(){} 子類方法B:int eat(){} 兩者雖然參數相同,可是返回類型不同,所以不是重寫。
父類方法A:int eat(){} 子類方法B:long eat(){} 返回類型雖然兼容父類,但是不同就是不同,所以不是重寫。
D、重寫規則之四:
重寫方法不能拋出新的異常或者比被重寫方法聲明的檢查異常更廣的檢查異常。但是可以拋出更少,更有限或者不拋出異常。
下面這段話是百度知道上一個人對於上面這句話的解釋,我覺得蠻形象的,所以就拿出來share一下
子類拋出的異常類型不能比父類拋出的異常類型更寬泛!
對於這句話你還少了一個條件應該是子類重寫父類方法不能拋出比父類更寬的異常類型的把。
其實理解這個很簡單,比如說憲法規定罵人只承擔民事責任,到了刑法裏就不能說直接槍斃了,這就是一個約束能力的問題,
子類行爲不能超出父類約束範疇。否者就容易亂套。就像父類的某方法公有的,子類就不能重寫改成私有的了。這就是一個約束力的問題。
還有我查到說拋出runtime異常沒有問題。運行時異常雖然可以不用捕獲。但如果其本身已經超出了父類的範圍呢?
這個還是拿憲法民事責任來說把,憲法說罵人教育一下就可以了,到了省裏說道個歉就可以了,但是到了市裏了,不光道歉還要寫檢討。
這些都是可以的,因爲他們本身就有處理這個事件的能力。子類方法他可以不管RuntimeException之類的異常,這是前提,
就算你父類方法聲明的異常更小,我可以行使我拋出RuntimeException異常的權利,這個是我的本身就有的權利。
這就像是地方政策和國家政策相抵觸的時候,老百姓可以直接往國家報告,可以不經過地方政府一樣,因爲老百姓有直接上報國家的權利。
子類有RuntimeException異常不報告的權利,就算你父類規定個更低的異常,我一樣可以上報,只要你比RuntimeException低級就可以。
這就好比,賣國賊選擇了賣國,他們的子女就不能愛國了一樣!
import java.io.*;
public class Test {
public static void main (String[] args) {
Animal h = new Horse();
try {
h.eat();
}
catch (Exception e) {
}
}
}
class Animal {
public void eat() throws Exception{
System.out.println ("Animal is eating.");
throw new Exception();
}
}
class Horse extends Animal{
public void eat() throws IOException{
System.out.println ("Horse is eating.");
throw new IOException();
}
}
這個例子中,父類拋出了檢查異常Exception,子類拋出的IOException是Exception的子類,也即是比被重寫的方法拋出了更有限的異常,這是可以的。如果反過來,父類拋出IOException,子類拋出更爲寬泛的Exception,那麼不會通過編譯的。
注意:這種限制只是針對檢查異常,至於運行時異常RuntimeException及其子類不再這個限制之中。
E、重寫規則之五:
不能重寫被標識爲final的方法。
F、重寫規則之六:
如果一個方法不能被繼承,則不能重寫它。
比較典型的就是父類的private方法。下例會產生一個有趣的現象。
public class Test {
public static void main (String[] args) {
//Animal h = new Horse();
Horse h = new Horse();
h.eat();
}
}
class Animal {
private void eat(){
System.out.println ("Animal is eating.");
}
}
class Horse extends Animal{
public void eat(){
System.out.println ("Horse is eating.");
}
}
這段代碼是能通過編譯的。表面上看來違反了第六條規則,但實際上那是一點巧合。Animal類的eat()方法不能被繼承,因此Horse類中的 eat()方法是一個全新的方法,不是重寫也不是重載,只是一個只屬於Horse類的全新的方法!這點讓很多人迷惑了,但是也不是那麼難以理解。
main()方法如果是這樣:
Animal h = new Horse();
//Horse h = new Horse();
h.eat();
編譯器會報錯,爲什麼呢?Horse類的eat()方法是public的啊!應該可以調用啊!請牢記,多態只看父類引用的方法,而不看子類對象的方法!