JAVA方法的重載(overload)和覆蓋(override)
方法的重載(overload)和覆蓋(override)
有的時候,類的同一種功能有多種實現方式,到底采用哪種實現方式,取決於調用者給定的參數。例如我們最常用的System.out.println()能夠打印出任何數據類型的數據,它有多種實現方式。運行時,Java虛擬機先判斷給定參數的類型,然後決定執行哪個println()方法。
重載(overload):對於類的方法(包括從父類中繼承的方法),方法名相同,參數列表不同的方法之間就構成了重載關系。這裏有兩個問題需要註意:
(1) 什麽叫參數列表?參數列表又叫參數簽名,指三樣東西:參數的類型,參數的個數,參數的順序。這三者只要有一個不同就叫做參數列表不同。
(2) 重載關系只能發生在同一個類中嗎?非也。這時候你要深刻理解繼承,要知道一個子類所擁有的成員除了自己顯式寫出來的以外,還有父類遺傳下來的。所以子類中的某個方法和父類中繼承下來的方法也可以發生重載的關系。
大家在使用的時候要緊扣定義,看方法之間是否是重載關系,不用管方法的修飾符和返回類型以及拋出的異常,只看方法名和參數列表。而且要記住,構造器也可以重載。
覆蓋 (override):也叫重寫,就是在當父類中的某些方法不能滿足要求時,子類中改寫父類的方法。當父類中的方法被覆蓋了後,除非用super關鍵字,否則就無法再調用父類中的方法了。
發生覆蓋的條件:
1、“三同一不低” 子類和父類的方法名稱
註:Java SE5中添加了協變返回類型,即子類中覆蓋方法可以返回基類中被覆蓋方法所返回類型的子類類型。如:基類中的被覆蓋方法返回類型為Shape,Circle為Shape 的子類,則子類中的覆蓋方法getArea()可以返回Circle類型。此時返回類型不相同。
2、子類方法不能拋出比父類方法更多的異常。即子類方法所拋出的異常必須和父類方法所拋出的異常一致,或者是其子類,或者什麽也不拋出;
3、被覆蓋的方法不能是final類型的。因為final修飾的方法是無法覆蓋的。
4、被覆蓋的方法不能為private
5、被覆蓋的方法不能為static。所以如果父類中的方法為靜態的,而子類中的方法不是靜態的,但是兩個方法除了這一點外其他都滿足覆蓋條件,那麽會發生編譯錯誤。反之亦然。即使父類和子類中的方法都是靜態的,並且滿足覆蓋條件,但是仍然不會發生覆蓋,因為靜態方法是在編譯的時候把靜態方法和類的引用類型進行匹配。
方法的覆蓋和重載具有以下相同點:
都要求方法同名
都可以用於抽象方法和非抽象方法之間
方法的覆蓋和重載具有以下不同點:
方法覆蓋要求參數列表(參數簽名)必須一致,而方法重載要求參數列表必須不一致。
方法覆蓋要求返回類型必須一致,方法重載對此沒有要求。
方法覆蓋只能用於子類覆蓋父類的方法,方法重載用於同一個類中的所有方法(包括從父類中繼承而來的方法)
方法覆蓋對方法的訪問權限和拋出的異常有特殊的要求,而方法重載在這方面沒有任何限制。
父類的一個方法只能被子類覆蓋一次,而一個方法可以在所有的類中可以被重載多次。
另外,對於屬性(成員變量)而言,是不能重載的,只能覆蓋。
註:可以在覆蓋的方法前面加上註解@Override,加上後當該方法不滿足對父類方法的覆蓋條件(三同一不低)時,編譯會出現錯誤提示。
public class FieldDemo { public static void main(String[] args){ Student t = new Student("Jack"); Person p = t;//父類創建的引用指向子類所創建的對象 System.out.println(t.name+","+p.name); System.out.println(t.getName()+","+p.getName()); } } class Person{ String name; int age; public String getName(){ return this.name; } } class Student extends Person{ String name; // 屬性和父類屬性名相同,但在做開發時一般不會和父類屬性名相同!! public Student(String name){ this.name = name; super.name = "Rose"; // 為父類中的屬性賦值 } public String getName(){ return this.name; } }
返回結果是:
Jack,Rose
Jack,Jack
原因是:在Java中,屬性綁定到類型,方法綁定到對象!
public class Car { public void Tick() { Show(); } private void Show() { System.out.println("fu show"); } } public class MyCar extends Car { public int num = 8; public void Show() { System.out.println("Zi show"); } } public class Demo { /** * 主函數入口 * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub MyCar c = new MyCar(); c.Tick(); } }
JAVA方法的重載(overload)和覆蓋(override)