面試突擊13:方法優先呼叫可選引數還是固定引數?

面試突擊13:方法優先呼叫可選引數還是固定引數?

面試合集:https://gitee。com/mydb/interview

可選引數(varargs)是 JDK 5 中新增的特性,也叫變長引數或可變引數。它是指一個方法的引數中可以用“。。。”來表示此方法可以接受無窮個引數,這種表示方法就叫可選引數。

可選引數的語法如下:

public void method(資料型別。。。 引數名稱){ // 方法體}

可選引數基本用法如下:

public class ArgumentExample { public static void main(String[] args) { // 呼叫可選引數 method(“Java”); System。out。println(); // 呼叫可選引數 method(“MySQL”, “Redis”); // 呼叫可選引數 System。out。println(); method(“Spring”, “Spring MVC”, “Spring Boot”); } /** * 可選引數方法 */ public static void method(String。。。 names) { for (String item : names) { System。out。println(item); } }}

以上程式的執行結果如下圖所示:

面試突擊13:方法優先呼叫可選引數還是固定引數?

固定引數

固定引數的概念恰好與可選引數相反,固定引數也就是普通的引數,一個方法中有固定的引數型別和個數且沒有“。。。”修飾就是固定引數。JDK 5 之前所有的方法傳參都是固定引數,如下程式碼所示:

public class ArgumentExample { public static void main(String[] args) { method(“Java”); } /** * 固定引數方法 */ public static void method(String name) { System。out。println(“固定引數:” + name); }}

可選引數注意事項

可選引數在使用時要注意以下 4 個問題。

1。可選引數是從0到無窮

可選引數的呼叫個數是從 0 到無窮,而不是從 1 到無窮,這點需要注意一下,如以下程式碼所示:

public class ArgumentExample { public static void main(String[] args) { method(); } /** * 可選引數方法 */ public static void method(String。。。 names) { System。out。println(“可選引數數量:” + names。length); }}

以上程式的執行結果如下圖所示:

面試突擊13:方法優先呼叫可選引數還是固定引數?

從上述程式碼可以看出,可選引數即使不傳遞任何引數,也就是 0 個引數,也是能正常呼叫到的。

2。一個方法只能有一個可選引數

一個方法中只能有一個可選引數,如果有多個可選引數程式會報錯,如下圖所示:

面試突擊13:方法優先呼叫可選引數還是固定引數?

3。可選引數必須要放在方法最後

可選引數如果不放在方法引數的最後面,那麼編譯器也會報錯,如下圖所示:

面試突擊13:方法優先呼叫可選引數還是固定引數?

4。可選引數和其他同名方法組成方法過載

可選引數和其他的同名方法可以並存,並且它們組成了方法過載,如下程式碼所示:

面試突擊13:方法優先呼叫可選引數還是固定引數?

優先呼叫固定引數還是可選引數?

基本知識點介紹完,接下來咱們回到本文的主題,當一個方法中有兩類引數:固定引數和可選引數時,究竟是先呼叫固定引數呢?還是先呼叫可選引數呢?

接下來咱們使用一段程式碼來測試一下:

public class ArgumentExample { public static void main(String[] args) { method(“磊哥聊程式設計”); } /** * 固定引數方法 */ public static void method(String name) { System。out。println(“呼叫固定引數:” + name); } /** * 可選引數方法 */ public static void method(String。。。 names) { System。out。println(“呼叫可選引數:” + names。length); }}

以上程式的執行結果如下:

面試突擊13:方法優先呼叫可選引數還是固定引數?

結論

從上面的結果可以看出,

當程式中有固定引數和可選引數時,優先呼叫固定引數,而非可選引數

原因分析

看到這,可能有朋友已經意識到了,如果你看過我上一篇《為什麼不同返回型別不算方法過載?》就全明白了,究竟是先呼叫可選引數還是固定引數?上一篇文章在介紹方法過載呼叫的優先順序規則裡已經說過了:其中

可選引數的呼叫優先順序是最低的,在固定引數和可選引數之間還有其他的呼叫選項

。因為有些朋友沒注意到,或者沒看到,所以我這裡再簡單的回顧一下。

第1優先順序:精準引數匹配

方法過載會優先呼叫和方法引數型別一模一樣的固定引數方法。

第2優先順序:呼叫基本型別自動轉換成更大的基本型別

如果是基本資料型別,那麼方法過載呼叫的第 2 匹配原則是自動轉換成更大的基本資料型別,如以下程式碼:

public class OverloadExample { public static void main(String[] args) { OverloadExample example = new OverloadExample(); example。method(12); } public void method(long num) { System。out。println(“呼叫 long 方法”); } public void method(Integer num) { System。out。println(“呼叫 Integer 方法”); } public void method(Object num) { System。out。println(“呼叫 Object 方法”); } public void method(int。。。 num) { // 可選引數 System。out。println(“呼叫 int。。。 方法”); }}

以上程式的執行結果如下圖所示:

面試突擊13:方法優先呼叫可選引數還是固定引數?

第3優先順序:自動裝/拆箱匹配

如果存在基本型別對應的包裝型別,或者是包裝型別對應的基本型別的方法過載,那麼會優先呼叫自動裝箱或自動拆箱的方法過載,如以下程式碼所示:

public class OverloadExample { public static void main(String[] args) { OverloadExample example = new OverloadExample(); example。method(12); } public void method(Integer num) { System。out。println(“呼叫 Integer 方法”); } public void method(Object num) { System。out。println(“呼叫 Object 方法”); } public void method(int。。。 num) { // 可選引數 System。out。println(“呼叫 int。。。 方法”); }}

以上程式的執行結果如下圖所示:

面試突擊13:方法優先呼叫可選引數還是固定引數?

第4優先順序:按照繼承路線依次向上匹配父類

當有父類引數時會優先呼叫父類過載方法,如下程式碼所示:

public class OverloadExample { public static void main(String[] args) { OverloadExample example = new OverloadExample(); example。method(12); } public void method(Object num) { System。out。println(“呼叫 Object 方法”); } public void method(int。。。 num) { // 可選引數 System。out。println(“呼叫 int。。。 方法”); }}

以上程式的執行結果如下圖所示:

面試突擊13:方法優先呼叫可選引數還是固定引數?

第5優先順序:可選引數匹配

可選引數的呼叫優先順序是最低的,當一個類中只有可選引數方法時,才會呼叫可選引數方法。

總結

可選引數是 JDK 5 中新增的以“。。。”格式存在的引數型別,可選引數可以匹配 0 到無窮個引數,但一個方法中只能有一個可選引數,且可選引數要放在方法引數的最後面。它可以和固定引數組成方法過載,但可選引數的呼叫優先順序是最低的。

是非審之於己,譭譽聽之於人,得失安之於數。