重載(Overloading)和重寫(Overriding)是Java中兩個比較重要的概念。可是對於新手來講也比較容易混淆。本文經過兩個簡單的例子說明了他們之間的區別。函數
簡單說,就是函數或者方法有一樣的名稱,可是參數列表不相同的情形,這樣的同名不一樣參數的函數或者方法之間,互相稱之爲重載函數或者方法。spa
重寫指的是在Java的子類與父類中有兩個名稱、參數列表都相同的方法的狀況。因爲他們具備相同的方法簽名,因此子類中的新方法將覆蓋父類中原有的方法。code
關於重載和重寫,你應該知道如下幾點:對象
一、重載是一個編譯期概念、重寫是一個運行期間概念。blog
二、重載遵循所謂「編譯期綁定」,即在編譯時根據參數變量的類型判斷應該調用哪一個方法。繼承
三、重寫遵循所謂「運行期綁定」,即在運行的時候,根據引用變量所指向的實際對象的類型來調用方法編譯器
四、由於在編譯期已經肯定調用哪一個方法,因此重載並非多態。而重寫是多態。重載只是一種語言特性,是一種語法規則,與多態無關,與面向對象也無關。(注:嚴格來講,重載是編譯時多態,即靜態多態。可是,Java中提到的多態,在不特別說明的狀況下都指動態多態)編譯
下面是一個重寫的例子,看完代碼以後不妨猜想一下輸出結果:class
class Dog{ public void bark(){ System.out.println("woof "); } } class Hound extends Dog{ public void sniff(){ System.out.println("sniff "); } public void bark(){ System.out.println("bowl"); } } public class OverridingTest{ public static void main(String [] args){ Dog dog = new Hound(); dog.bark(); } }
輸出結果:變量
bowl
上面的例子中,dog
對象被定義爲Dog
類型。在編譯期,編譯器會檢查Dog類中是否有可訪問的bark()
方法,只要其中包含bark()
方法,那麼就能夠編譯經過。在運行期,Hound
對象被new
出來,並賦值給dog
變量,這時,JVM是明確的知道dog
變量指向的實際上是Hound
對象的引用。因此,當dog
調用bark()
方法的時候,就會調用Hound
類中定義的bark()
方法。這就是所謂的動態多態性。
參數列表必須徹底與被重寫方法的相同;
返回類型必須徹底與被重寫方法的返回類型相同;
訪問級別的限制性必定不能比被重寫方法的強;
訪問級別的限制性能夠比被重寫方法的弱;
重寫方法必定不能拋出新的檢查異常或比被重寫的方法聲明的檢查異常更普遍的檢查異常
重寫的方法可以拋出更少或更有限的異常(也就是說,被重寫的方法聲明瞭異常,但重寫的方法能夠什麼也不聲明)
不能重寫被標示爲final的方法;
若是不能繼承一個方法,則不能重寫這個方法。
class Dog{ public void bark(){ System.out.println("woof "); } //overloading method public void bark(int num){ for(int i=0; i<num; i++) System.out.println("woof "); } }
上面的代碼中,定義了兩個bark方法,一個是沒有參數的bark方法,另一個是包含一個int類型參數的bark方法。在編譯期,編譯期能夠根據方法簽名(方法名和參數狀況)狀況肯定哪一個方法被調用。
被重載的方法必須改變參數列表;
被重載的方法能夠改變返回類型;
被重載的方法能夠改變訪問修飾符;
被重載的方法能夠聲明新的或更廣的檢查異常;
方法可以在同一個類中或者在一個子類中被重載。