面試官:Java的重寫和過載有什麼區別?

沉默王二發表於2020-04-07

老讀者都知道了,七年前,我從美女很多的蘇州回到美女更多的洛陽(美化了),抱著一幅“從二線城市退居三線城市”的心態,投了不少簡歷,也“約談”了不少面試官,但僅有兩三個令我感到滿意。其中有一位叫老馬,至今還活在我的微信通訊錄裡。他當時扔了一個面試題把我砸懵了:“王二,Java 的重寫(Override)和過載(Overload)有什麼區別?

那年我二十三歲,正值青春年華,大約就是周杰倫釋出《八度空間》的年紀,自認為所有的面試題都能對答如流,結果沒想到啊,被“刁難”了——原來洛陽這塊網際網路的荒漠也有技術專家啊。現在回想起來,臉上不自覺地泛起了羞愧的紅暈:主要是自己當時太菜了。不管怎麼說,七年時間過去了,我的技術功底已經非常紮實,有能力寫篇文章剖析一下 Java 的重寫和過載了,只要能給後來者一些參考,我就覺得做了天大的善事。

好了,讓我們來步入正題。先來看一段重寫的程式碼吧。

class LaoWang{
    public void write() {
        System.out.println("老王寫了一本《基督山伯爵》");
    }
}
public class XiaoWang extends LaoWang {
    @Override
    public void write() {
        System.out.println("小王寫了一本《茶花女》");
    }
}

重寫的兩個方法名相同,方法引數的個數也相同;不過一個方法在父類中,另外一個在子類中。就好像父類 LaoWang 有一個 write() 方法(無參),方法體是寫一本《基督山伯爵》;子類 XiaoWang 重寫了父類的 write() 方法(無參),但方法體是寫一本《茶花女》。

來寫一段測試程式碼。

public class OverridingTest {
    public static void main(String[] args) {
        LaoWang wang = new XiaoWang();
        wang.write();
    }
}

大家猜結果是什麼?

小王寫了一本《茶花女》

在上面的程式碼中,們宣告瞭一個型別為 LaoWang 的變數 wang。在編譯期間,編譯器會檢查 LaoWang 類是否包含了 write() 方法,發現 LaoWang 類有,於是編譯通過。在執行期間,new 了一個 XiaoWang 物件,並將其賦值給 wang,此時 Java 虛擬機器知道 wang 引用的是 XiaoWang 物件,所以呼叫的是子類 XiaoWang 中的 write() 方法而不是父類 LaoWang 中的 write() 方法,因此輸出結果為“小王寫了一本《茶花女》”。

再來看一段過載的程式碼吧。

class LaoWang{
    public void read() {
        System.out.println("老王讀了一本《Web全棧開發進階之路》");
    }
    
    public void read(String bookname) {
        System.out.println("老王讀了一本《" + bookname + "》");
    }
}

過載的兩個方法名相同,但方法引數的個數不同,另外也不涉及到繼承,兩個方法在同一個類中。就好像類 LaoWang 有兩個方法,名字都是 read(),但一個有引數(書名),另外一個沒有(只能讀寫死的一本書)。

來寫一段測試程式碼。

public class OverloadingTest {
    public static void main(String[] args) {
        LaoWang wang = new LaoWang();
        wang.read();
        wang.read("金瓶梅");
    }
}

這結果就不用猜了。變數 wang 的型別為 LaoWang,wang.read() 呼叫的是無參的 read() 方法,因此先輸出“老王讀了一本《Web全棧開發進階之路》”;wang.read("金瓶梅") 呼叫的是有參的 read(bookname) 方法,因此後輸出“老王讀了一本《金瓶梅》”。在編譯期間,編譯器就知道這兩個 read() 方法時不同的,因為它們的方法簽名(=方法名稱+方法引數)不同。

簡單的來總結一下:

1)編譯器無法決定呼叫哪個重寫的方法,因為只從變數的型別上是無法做出判斷的,要在執行時才能決定;但編譯器可以明確地知道該呼叫哪個過載的方法,因為引用型別是確定的,引數個數決定了該呼叫哪個方法。

2)多型針對的是重寫,而不是過載。

哎,後悔啊,早年我要是能把這道面試題吃透的話,也不用被老馬刁難了。吟一首詩感慨一下人生吧。

青青園中葵,朝露待日晞。
陽春佈德澤,萬物生光輝。
常恐秋節至,焜黃華葉衰。
百川東到海,何時復西歸?
少壯不努力,老大徒傷悲

另外,我想要告訴大家的是,重寫(Override)和過載(Overload)是 Java 中兩個非常重要的概念,新手經常會被它們倆迷惑,因為它們倆的英文名字太像了,中文翻譯也只差一個字。難,太難了。

好了,我親愛的讀者朋友,以上就是本文的全部內容了。能看到這裡的都是最優秀的程式設計師,二哥必須要伸出大拇指為你點個贊?。原創不易,如果覺得有點用的話,請不要吝嗇你手中點讚的權力,因為這將是我最強的寫作動力。我們下篇文章見!

相關文章