方法覆蓋指的是如果在子類中定義的一個方法,其名稱,返回類型及參數簽名正好與父類中的某個方法的名稱,返回類型及參數簽名相匹配,那麼就可以說子類的方法覆蓋了父類的方法。
方法的覆蓋必須滿足多種約束,下面將一一進行介紹:
(1)子類方法的名稱,返回類型及參數簽名必須與父類方法的名稱,返回類型及參數簽名一致。
例:如下代碼將會導致編譯錯誤
public class Base { public void method(){ } } public class Sub extends Base { public int method(){//編譯錯誤,返回類型不一致 return 0; } }
若在子類中先將父類的method()方法覆蓋,再重載,那麼將是合法的。
public class Base { public void method(){ } } public class Sub extends Base { public void method(){ } public int method(int a){ return 0; } }
(2)子類方法不能縮小父類方法的訪問權限。
例:如下代碼將會導致編譯錯誤。
public class Base { public void method(){ } } public class Sub extends Base { private void method(){//編譯錯誤,子類方法縮小了父類方法的訪問權限 } }
錯誤原因分析:
假如沒有這個限制,將會與java多態機制發生衝突。如對於以下代碼
Base base = new Sub(); base.method();
Java編譯器認爲以上是合法代碼,在運行時候根據動態綁定規則,Java虛擬機會調用base變量所引用的Sub實例的method()方法,如果這個方法是private類型的,Java虛擬機就無法訪問它。
(3)子類不能拋出比父類更多的異常。 子類拋出的異常必須和父類拋出的異常相同或者子類拋出的異常是父類拋出的異常的子類。
(4)方法覆蓋只存在子類和父類(包括直接父類和間接父類)之間。 在同一個類中方法只能被重載不能被覆蓋。
(5)父類的靜態方法不能被子類覆蓋爲非靜態方法。
例:如下代碼將導致編譯錯誤
public class Base { public static void method(){ } } public class Sub extends Base { public void method(){ //編譯出錯 } }
(6)子類可以定義與父類的靜態方法同名的靜態方法。但須滿足方法覆蓋約束條件即方法的參數簽名一致,返回類型一致,不能縮小父類方法的訪問權限,不能拋出比父類方法更多的異常。
例:如下代碼是合法的:
public class Base { static int method(int a) throws Exception{ return 0; } } import java.io.IOException; public class Sub extends Base { public static int method(int a) throws IOException{ return 0; } }
(7)父類的非靜態方法不能被子類覆蓋爲靜態方法。
public class Base { public void method(){ } } public class Sub extends Base { public static void method(){ //編譯出錯 } }
(8)父類的私有方法不能被子類覆蓋。
例:如下代碼:
public class Base { private void say(){ System.out.println("I am Base Class"); } public void speak(){ say(); } } public class Sub extends Base { public void say(){ System.out.println("I am Sub Class"); } public static void main(String[] args) { Sub sub = new Sub(); sub.speak(); } }
運行結果是:
I am Base Class
如果把Base類的say()方法改成public型的,即:
private void say(){ System.out.println("I am Base Class"); }
那麼,運行結果爲:
I am Sub Class
(9)父類的抽象方法可以被子類通過兩種方式覆蓋。
1)子類實現父類的抽象方法
2)子類重新聲明父類的抽象方法
例:如下代碼合法:
public abstract class Base { public abstract void method1(); public abstract void method2(); } public abstract class Sub extends Base { public void method1(){ } public abstract void method2(); }
(10)父類的非抽象方法可以被覆蓋爲抽象方法
例:如下代碼合法:
public class Base { void method(){ } } public abstract class Sub extends Base { public abstract void method(); }