本文以實例詳細分析了Java中重載與重寫的區別,有興趣的朋友可以參考一下。
一、重載(Overloading):
(1) 方法重載是讓類別以統一的方式處理不同類型資料的手段。多個同名函數同時存在,具有不同的參數數量/型別。
重載Overloading是一個類別中多態性的一種表現。
(2)Java的方法重載,就是在類別中可以創建多個方法,它們具有相同的名字,但具有不同的參數和不同的定義。
呼叫方法時透過傳遞給它們的不同參數個數和參數類型來決定具體使用哪個方法, 這就是多態性。
(3) 重載的時候,方法名稱要一樣,但是參數型別和個數不一樣,回傳值型別可以相同也可以不相同。無法以返回型別作為重載函數的區分標準。
下面是重載的例子:
package c04.answer;//這是包名//這是這個程式的第一種程式方法,在main方法中先建立一個Dog類別實例,然後在Dog類別的建構方法中利用this關鍵字呼叫不同的bark方法。不同的重載方法bark是根據其參數類型的不同而區分的。 //注意:除構造器以外,編譯器禁止在其他任何地方呼叫構造器。 package c04.answer;public class Dog {Dog(){this.bark();}void bark()//bark()方法是重載方法{System.out.println(/"no barking!/"); this.bark(/"female/", 3.4);}void bark(String m,double l)//注意:重載的方法的回傳值都是一樣的,{System.out.println(/"a barking dog!/");this.bark(5, /"China/");}void bark(int a,String n)//不能以回傳值區分重載方法,而只能以「參數型別」與「類別名稱」來區分{System.out.println(/"a howling dog/"); }public static void main(String[] args){Dog dog = new Dog();//dog.bark(); [Page]//dog.bark(/"male/", /"yellow/");// dog.bark(5, /"China/");
二、重寫(Overriding)
(1) 父類別與子類別之間的多態性,對父類別的函數進行重新定義。如果在子類別中定義某方法與其父類別有相同的名稱和參數,我們說該方法被重寫(Overriding)。在中,子類別可繼承父類別中的方法,而不需要重新編寫相同的方法。
但有時子類別並不想原封不動地繼承父類別的方法,而是想作一定的修改,這就需要採用方法的重寫。
方法重寫又稱方法覆蓋。
(2)若子類別中的方法與父類別中的某一方法具有相同的方法名稱、傳回型別和參數表,則新方法會覆寫原有的方法。
如需父類別中原有的方法,可使用super關鍵字,該關鍵字引用了目前類別的父類別。
(3)子類別函數的存取修飾權限不能少於父類別的;
下面是重寫的例子:
概念:即呼叫物件方法的機制。
動態綁定的內幕:
1、編譯器檢查物件聲明的類型和方法名,從而取得所有候選方法。試著把上例Base類別的test註解掉,這時再編譯就無法通過。
2.重載決策:編譯器檢查方法呼叫的參數類型,從上述候選方法選出唯一的那一個(其間會有隱含型別轉換)。
如果編譯器找到多於一個或沒找到,此時編譯器就會報錯。試著把上例Base類別的test(byte b)註解掉,這時運行結果是1 1。
3.若方法型別為priavte static final ,java採用靜態編譯,編譯器會準確知道該呼叫哪個方法。
4.當程式運作並且使用動態綁定來呼叫一個方法時,那麼虛擬機器必須呼叫物件的實際類型相符的方法版本。
在範例中,b所指向的實際型別是TestOverriding,所以b.test(0)呼叫子類別的test。
但是,子類別並沒有重寫test(byte b),所以b.test((byte)0)呼叫的是父類別的test(byte b)。
如果把父類別的(byte b)註解掉,則透過第二步驟隱含型別轉換為int,最終呼叫的是子類別的test(int i)。
三、學習總結:
多態性是物件導向程式設計的特性,和方法無關,
簡單說,就是同樣的一個方法能夠根據輸入資料的不同,做出不同的處理,即方法的重載――有不同的參數列表(靜態多態性)
而當子類別繼承自父類別的相同方法,輸入資料一樣,但要做出有別於父類別的回應時,你就要覆寫父類別方法,
即在子類別中重寫此方法――相同參數,不同實作(動態多態性)
OOP三大特性:繼承,多型,封裝。
public class Base{void test(int i){System.out.print(i);}void test(byte b){System.out.print(b);}}public class TestOverriding extends Base{void test(int i ){i++;System.out.println(i);}public static void main(String[]agrs){Base b=new TestOverriding();b.test(0)b.test((byte)0)}}
這時的輸出結果是1 0,這是運行時動態綁定的結果。
重寫的主要優點是能夠定義某個子類別特有的特徵:
publicclassFather{publicvoidspeak(){System.out.println(Father);}}publicclassSonextendsFather{publicvoidspeak(){System.out.println("son");}}
這也叫做多態性,重寫方法只能存在於具有繼承關係中,而重寫方法只能重寫父類別非私有的方法。
當上例中Father類別speak()方法被private時,Son類別無法重寫Father類別speak()方法,此時Son類別speak()方法相當與在Son類別中定義的一個speak()方法。
Father類別speak()方法一但被final時,無論此方法被public,protected及預設所修飾時,Son類別根本無法重寫Father類別speak()方法,
試圖編譯程式碼時,編譯器會報錯。例:
publicclassFather{finalpublicvoidspeak(){System.out.println("Father");}}publicclassSonextendsFather{publicvoidspeak(){System.out.println("son");}}//編譯器會報錯;
Father類別speak()方法被預設修飾時,只能在同一包中,被其子類別被重寫,如果不在同一包則不能重寫。
Father類別speak()方法被protoeted時,不只在同一包中,被其子類別被重寫,還可以不同套件的子類別重寫。
重寫方法的規則:
1、參數列表必須完全與被重寫的方法相同,否則不能稱之為重寫而是重載。
2、傳回的類型必須一直與被重寫的方法的回傳類型相同,否則不能稱之為重寫而是重載。
3.存取修飾符的限制一定大於被重寫方法的存取修飾符(public>protected>default>private)
4.重寫方法一定不能拋出新的檢查異常或比被重寫方法申明更加寬泛的檢查型異常。例如:
父類別的一個方法申明了一個檢查異常IOException,在重寫這個方法是就不能拋出Exception,只能拋出IOException的子類異常,可以拋出非檢查異常。
而重載的規則:
1、必須具有不同的參數列表;
2、可以有不責罵的回傳類型,只要參數清單不同就可以了;
3.可以有不同的存取修飾符;
4、可以拋出不同的異常;
重寫與重載的差別在於:
重寫多態性起作用,對呼叫被重載過的方法可以大幅減少程式碼的輸入量,同一個方法名稱只要往裡面傳遞不同的參數就可以擁有不同的函數或傳回值。
用好重寫和重載可以設計一個結構清晰而簡潔的類,可以說重寫和重載在編寫程式碼過程中的作用非同一般.