Java 重載方法的匹配規則-含有變長參數方法的匹配
本文用一個例子來展示 含有變長參數的重載方法是如何匹配的
public class demo {
void invoke(Object obj, Object... args) {
System.out.println(1);
}
void invoke(String s, Object obj, Object... args) {
System.out.println(2);
}
public static void main(String[] args) {
demo d = new demo();
d.invoke(null); //1
d.invoke(null, 1); //2
d.invoke(null,2,1); //2
d.invoke(1,2,1); //1
}
}
重載方法的匹配規則:
——引用自《深入拆解 Java 虛擬機》
重載的方法在編譯過程中即可完成識別。具體到每一個方法調用,Java 編譯器會根據所傳入參數的聲明類型(注意與實際類型區分)來選取重載方法。選取的過程其實分為三個階段:
-
在不考慮對基本類型自動裝拆箱(auto-boxing,auto-unboxing),以及可變長參數的情況下選取重載方法;
-
如果在第 1 個階段中沒有找到適配的方法,那么在允許自動裝拆箱,但不允許可變長參數的情況下選取重載方法;
-
如果在第 2 個階段中沒有找到適配的方法,那么在允許自動裝拆箱以及可變長參數的情況下選取重載方法。
PS:如果 Java 編譯器在同一個階段中找到了多個適配的方法,那么它會在其中選擇一個最為貼切 的,而決定貼切程度的一個關鍵就是形式參數類型的繼承關系。
舉個例子:當傳入 null 時,它既可以匹配第一個方法中聲明為 Object 的形式參數,也可 以匹配第二個方法中聲明為 String 的形式參數。由於 String 是 Object 的子類,因此 Java 編譯 器會認為第二個方法更為貼切。
結合例子
根據以上理論,結合例子可以看到:
- d.invoke(null);方法執行時滿足1階段的匹配規則,所以打印結果為 1;
- d.invoke(null,1);方法執行時滿足1階段的匹配規則,故打印結果為 2;
- d.invoke(null,2,1);方法執行時滿足階段2階段的匹配規則,所以打印 2
- d.invoke(1,2,1);方法執行時滿足階段2階段的匹配規則,同時第一個參數無法匹配 String類型,故打印 1
無法精確匹配到方法時
Java 編譯器可能無法決定應該調用哪 個目標方法。
在這種情況下,編譯器會報錯,並且提示這個方法調用有二義性如圖所示: