Java——重載和重寫

前言

在程序設計中常常會遇到對對方法的重載或者重寫,下面將介紹重載和重寫。html

重載(Overloade)

重載出現的緣由

任何程序設計語言都具有的一項重要特性就是對名字的運用。當建立一個對象時,就給對象的存儲空間取了一個名字。方法名就是給某個動做取的名字。經過使用名字,咱們能夠引用全部對象和方法。名字起的好可使程序更易於理解和修改。java

在大多數程序設計語言中要求爲每一個方法提供惟一的標識符。不能使用print()的函數顯示了整數以後,又用一個名爲print()的函數顯示浮點數。即,每一個函數(方法)都要有惟一的名稱。這是迫使出現重載方法的理由之一。如果print()函數能夠被重載了,那麼就既能夠輸出整數也能夠輸出浮點數。或者又能夠舉例:咱們要計算兩個整數相加,咱們能夠設計方法爲int add(int a, int b)。調用add(10,10)咱們就能夠知道是計算兩個整數相加。此時,咱們又想計算兩個浮點數相加,由於add見名知意因此咱們繼續使用這個名字,那麼就須要方法double add(double a, double c)。因而,add()方法就被重載了。編程

在Java(和C++)裏,構造器是強制重載方法出現的另外一個緣由。構造器的名字由類名決定,那麼就只能有一個構造器。可是,又想使用多種方式建立對象又該怎麼辦呢?那麼就只有重載構造器,使得同名不一樣參的構造器同時存在。ide

重載的規則

方法重載是在一個類裏面,方法名相同,而參數不一樣,對返回值沒有強制要求能夠相同也能夠不一樣。方法重載須要注意一下幾點:函數

  • 被重載的方法必須改變參數列表(參數個數或者類型不同)
  • 被重載的方法介意改變返回類型和訪問修飾符
  • 被重載的方法能夠聲明新的或者更廣的檢查異常
  • 方法可以在同一個類中或者在一個子類中被重載
  • 不能夠返回值類型做爲分區重載函數的標準

區分重載方法

每一個重載的方法都有獨一無二的參數類型列表。因此在區分重載方法時,只能以類名和方法的形參列表做爲標準。this

那爲何不能使用方法的返回值來區分呢?設計

好比下面兩個方法,雖然它們有相同的名字和形式參數,可是卻很容易區分它們3d

void f(){}
int f() {return 1;}

只要編譯器能夠根據語境明確判斷出語義,好比在int x = f()中,那麼的確能夠根據此區分方法。不過,有時你並不關心方法的返回值,你想要的是方法調用的其餘效果,這時你可能會調用方法而忽略返回值。因此,向下面這樣的調用方法:code

f();

此時Java該怎樣判斷調用的是哪一個方法呢?別人也沒法理解這個代碼的含義。所以,依據方法的返回值來區分重載方法是行不通的。htm

重寫(Override)

重寫出現的緣由

先看一個例子

class Animal{
    public void printWhoIAm(){System.out.println("Animal")}
}
public class Dog extends Animal{
    public static void main(String args[]){
        Dog dog = new Dog();
        dog.printWhoIAm();
    }
} 
/*
output:
Animal
*/

當dog調用printWhoIAm()方法時,其實但願的是輸出「dog」,而不是Animal。要實現輸出「Dog」,想到了重載,但是重載要求被重載的方法具備不一樣的形參列表。這個方法不得行。dog調用的printWhoIAm()是父類中的,在子類中如果能夠重寫這個方法,那麼就能夠實現目的了。因而,重寫(覆寫)便產生了,爲了解決父類方法在子類中不適用,而讓子類重寫方法的方式。咱們解決以上代碼需求以下:

class Animal{
    public void printWhoIAm(){System.out.println("Animal")}
}
public class Dog extends Animal{
    //加上註解@Override能夠強制進行重寫的檢查 防止本身重寫錯誤
    @Override
    public void printWhoIAm(){System.out.println("Dog")}
    public static void main(String args[]){
        Dog dog = new Dog();
        dog.printWhoIAm();
    }
} 
/*
output:
Dog
*/

重寫的規則

  • 重寫是對父類容許訪問的方法的實現過程進行從新編寫,返回值不變或者爲子類、形參列表不能改變而且訪問控制權限不能嚴於父類。父類爲default包訪問權限,則子類就爲public或者default;若父類是public,則子類必須爲public。

  • 子類能夠重寫父類的除了構造器的任何方法。構造器是和類名相同的,不能被子類繼承,所以也不能夠被重寫。

  • 重寫方法不能拋出新的檢查異常或者比被重寫方法申明更加寬泛的異常。例如: 父類的一個方法申明瞭一個檢查異常 IOException,可是在重寫這個方法的時候不能拋出 Exception 異常,由於 Exception 是 IOException 的父類,只能拋出 IOException 的子類異常。

子類能夠重寫父類中訪問控制權限爲private的方法嗎?

答案是不能夠。父類中的private方法對子類來講是不可見的,就算子類中徹底按照重寫要求定義方法,也不能算重寫父類中的方法,實際上只是子類新增的一個方法。因此,只有非private方法才能夠被重寫。

super.方法()和this.方法()的區別

子類如果重寫了父類的方法,那麼父類原來的這個方法還能夠被調用嗎?答案是能夠的,使用super對父類的方法進行調用。

class Animal{
    public void printWhoIAm(){System.out.println("Animal")}
}
public class Dog extends Animal{
    //加上註解@Override能夠強制進行重寫的檢查 防止本身重寫錯誤
    @Override
    public void printWhoIAm(){System.out.println("Dog")}
    public void print(){
        super.printWhoIAm();
        printWhoIAm();// this.printWhoIAm();
    }
    public static void main(String args[]){
        Dog dog = new Dog();
        dog.print();
    }
} 
/*
output:
Animal
Dog
*/

使用this.方法()會先在本類中查找是否存在要調用的方法,若是不存在則查找父類中是否具有此方法。若是有則調用,不然出現編譯時錯誤。使用super.方法()會明確表示調用父類中的方法,直接去父類尋找要調用的方法。

重載和重寫的區別

區別 重載 重寫
參數列表 必須改 必定不能改
返回類型 能夠修改 必定不能改
訪問控制權限 能夠修改 不能比父類嚴格
異常 能夠修改 能夠減小或刪除,必定不能拋出新的或者更廣的異常
發生範圍 能夠在一個類中也能夠在子類中 在子類中

小結

須要注意的是重載和重寫的定義形式。引用菜鳥教程的兩句話和一張圖結束。

  • 方法重載是一個類中定義了多個方法名相同,而他們的參數的數量不一樣或數量相同而類型和次序不一樣,則稱爲方法的重載(Overloading)。

  • 方法重寫是在子類存在方法與父類的方法的名字相同,並且參數的個數與類型同樣,返回值也同樣的方法,就稱爲重寫(Overriding)

參考:
《Java編程思想》第四版
菜鳥教程http://www.runoob.com/java/java-override-overload.html

相關文章
相關標籤/搜索