1. 程式人生 > 其它 >方法重寫與方法過載

方法重寫與方法過載

Java方法重寫與過載
一、方法重寫(0veriding)
在Java程式中,類的繼承關係可以產生一個子類,子類繼承父類,它具備了父類所有的特徵,繼承了父類所有的方法和變數。
子類可以定義新的特徵,當子類需要修改父類的一些方法進行擴充套件,增大功能,程式設計者常常把這樣的一種操作方法稱為重寫,也叫稱為覆寫或覆蓋。

重寫體現了Java優越性,重寫是建立在繼承關係上,它使語言結構更加豐富。在Java中的繼承中,子類既可以隱藏和訪問父類的方法,也可以覆蓋繼承父類的方法。

在Java中覆蓋繼承父類的方法就是通過方法的重寫來實現的。所謂方法的重寫是指子類中的方法與父類中繼承的方法有完全相同的返回值型別、方法名、引數個數以及引數型別。

這樣,就可以實現對父類方法的覆蓋。如果子類將父類中的方法重寫了,呼叫的時候肯定是呼叫被重寫過的方法,那麼如果現在一定要呼叫父類中的方法該怎麼辦呢?

此時,通過使用super關鍵就可以實現這個功能,super關鍵字可以從子類訪問父類中的內容,如果要訪問被重寫過的方法,使用“super.方法名(引數列表)”的形式呼叫。

如果要使用super關鍵字不一定非要在方法重寫之後使用,也可以明確地表示某個方法是從父類中繼承而來的。使用super只是更加明確的說,要從父類中查詢,就不在子類查找了。

重寫的好處在於子類可以根據需要,定義特定於自己的行為。
也就是說子類能夠根據需要實現父類的方法。
在面向物件原則裡,重寫意味著可以重寫任何現有方法。例項如下:

class Animal{
public void move(){
System.out.println("動物可以移動");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 物件
Animal b = new Dog(); // Dog 物件
a.move();// 執行 Animal 類的方法
b.move();//執行 Dog 類的方法
}
}

//執行結果
動物可以移動
狗可以跑和走
登入後複製

在上面的例子中可以看到,儘管b屬於Animal型別,但是它執行的是Dog類的move方法。

這是由於在編譯階段,只是檢查引數的引用型別。

然而在執行時,Java虛擬機器(JVM)指定物件的型別並且執行該物件的方法。
因此在上面的例子中,之所以能編譯成功,是因為Animal類中存在move方法,然而執行時,執行的是特定物件的方法。
思考以下例子:

class Animal{
public void move(){
System.out.println("動物可以移動");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
public void bark(){
System.out.println("狗可以吠叫");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 物件
Animal b = new Dog(); // Dog 物件
a.move();// 執行 Animal 類的方法
b.move();//執行 Dog 類的方法
b.bark();
}
}
//以上例項編譯執行結果如下:
TestDog.java:30: cannot find symbol
symbol : method bark()
location: class Animal
b.bark();
登入後複製

該程式將丟擲一個編譯錯誤,因為b的引用型別Animal沒有bark方法。

二、重寫規則
在重寫方法時,需要遵循以下的規則:
(一) 父類方法的引數列表必須完全與被子類重寫的方法的引數列表相同,否則不能稱其為重寫而是過載。

(二) 父類的返回型別必須與被子類重寫的方法返回型別相同,否則不能稱其為重寫而是過載。

(三) Java中規定,被子類重寫的方法不能擁有比父類方法更加嚴格的訪問許可權。編寫過Java程式的人就知道,父類中的方法並不是在任何情況下都可以重寫的,當父類中方法的訪問許可權修飾符為private時,該方法只能被自己的類訪問,不能被外部的類訪問,在子類是不能被重寫的。如果定義父類的方法為public,在子類定義為private,程式執行時就會報錯。

(四) 由於父類的訪問許可權修飾符的限制一定要大於被子類重寫方法的訪問許可權修飾符,而private許可權最小。所以如果某一個方法在父類中的訪問許可權是private,那麼就不能在子類中對其進行重寫。如果重新定義,也只是定義了一個新的方法,不會達到重寫的效果。

(五) 在繼承過程中如果父類當中的方法丟擲異常,那麼在子類中重寫父類的該方法時,也要丟擲異常,而且丟擲的異常不能多於父類中丟擲的異常(可以等於父類中丟擲的異常)。換句話說,重寫方法一定不能丟擲新的檢查異常,或者比被重寫方法宣告更加寬泛的檢查型異常。例如,父類的一個方法申明瞭一個檢查異常IOException,在重寫這個方法時就不能丟擲Exception,只能丟擲IOException的子類異常,可以丟擲非檢查異常。同樣的道理,如果子類中建立了一個成員變數,而該變數和父類中的一個變數名稱相同,稱作變數重寫或屬性覆蓋。但是此概念一般很少有人去研究它,因為意義不大。

Super關鍵字的使用
當需要在子類中呼叫父類的被重寫方法時,要使用super關鍵字。

class Animal{
public void move(){
System.out.println("動物可以移動");
}
}
class Dog extends Animal{
public void move(){
super.move(); // 應用super類的方法
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal b = new Dog(); // Dog 物件
b.move(); //執行 Dog類的方法
}
}

//以上例項編譯執行結果如下:
動物可以移動
狗可以跑和走

三、方法過載(Overloading)
方法過載是讓類以統一的方式處理不同型別資料的一種手段。呼叫方法時通過傳遞給它們的不同個數和型別的引數來決定具體使用哪個方法,這就是多型性。

所謂方法過載是指在一個類中,多個方法的方法名相同,但是引數列表不同。引數列表不同指的是引數個數、引數型別或者引數的順序不同。

方法的過載在實際應用中也會經常用到。不僅是一般的方法,構造方法也可以過載。

在方法過載時,方法之間需要存在一定的聯絡,因為這樣可以提高程式的可讀性,一般只過載功能相似的方法。

過載是指我們可以定義一些名稱相同的方法,通過定義不同的引數來區分這些方法,然後再呼叫時,Java虛擬機器就會根據不同的引數列表來選擇合適的方法執行。也就是說,當一個過載方法被呼叫時,Java用引數的型別或個數來決定實際呼叫的過載方法。因此,每個過載方法的引數的型別或個數必須是不同。

雖然每個過載方法可以有不同的返回型別,但返回型別並不足以區分所使用的是哪個方法。

當Java呼叫一個過載方法是,引數與呼叫引數匹配的方法被執行。在使用過載要注意以下的幾點:
1.在使用過載時只能通過不同的引數列表,必須具有不同的引數列表。
2.不能通過訪問許可權、返回型別、丟擲的異常進行過載。
3.方法的異常型別和數目不會對過載造成影響。
4.可以有不同的返回型別,只要引數列表不同就可以了。
5.可以有不同的訪問修飾符。
6.可以丟擲不同的異常。

過載(overloading) 是在一個類裡面,方法名字相同,而引數不同。返回型別呢?可以相同也可以不同。
每個過載的方法(或者建構函式)都必須有一個獨一無二的引數型別列表。
只能過載建構函式

四、過載規則
被過載的方法必須改變引數列表;
被過載的方法可以改變返回型別;
被過載的方法可以改變訪問修飾符;
被過載的方法可以宣告新的或更廣的檢查異常;
方法能夠在同一個類中或者在一個子類中被過載。

public class Overloading {
public int test(){
System.out.println("test1");
return 1;
}
public void test(int a){
System.out.println("test2");
}
//以下兩個引數型別順序不同
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}
public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}
public static void main(String[] args){
Overloading o = new Overloading();
System.out.println(o.test());
o.test(1);
System.out.println(o.test(1,"test3"));
System.out.println(o.test("test4",1));
}
}
登入後複製

五、訪問修飾符
訪問修飾符 本類 同包 子類 其他
private √
預設 √ √
protected √ √ √
public √ √ √ √
六、總結
重寫與過載之間的區別

方法過載:
1、同一個類中
2、方法名相同,引數列表不同(引數順序、個數、型別)
3、方法返回值、訪問修飾符任意
4、與方法的引數名無關

方法重寫:
1、有繼承關係的子類中
2、方法名相同,引數列表相同(引數順序、個數、型別),方法返回值相同
3、訪問修飾符,訪問範圍需要大於等於父類的訪問範圍
4、與方法的引數名無關

區別點 過載方法 重寫方法
引數列表 必須修改 一定不能修改
返回型別 可以修改 一定不能修改
異常 可以修改 可以減少或刪除,一定不能丟擲新的或者更廣的異常
訪問 可以修改 一定不能做更嚴格的限制(可以降低限制)