這道經典題目考察 Java 方法重載解析時,固定參數優先於可變參數的核心規則。理解此機制對避免 API 設計歧義、排查「明明有更合適的方法卻未被調用」至關重要。
public class Ques1201 {
public static void main(String[] args) {
new Ques1201().sum(1, 2);
}
public void sum(int num1, int num2) { // 方法 A:固定雙參數
int temp = num1 + num2;
System.out.println("沒使用變長參數計算:" + temp);
}
public void sum(int num1, int... num2) { // 方法 B:可變參數
int temp = num1;
for (int n : num2) {
temp = temp + n;
}
System.out.println("使用變長參數計算:" + temp);
}
}
沒使用變長參數計算:3
JLS (Java Language Specification) 定義方法選擇按嚴格順序進行:
sum(int, int) 完美匹配 sum(1, 2),直接選中 方法 A。int ↔ Integer)。sum(int, int...) 屬於此階段。| 調用代碼 | 匹配方法 | 階段 | 輸出 |
|---|---|---|---|
sum(1, 2) | 方法 A (int, int) | 第一階段 | 沒使用變長參數計算:3 |
sum(1) | 方法 B (int, int...) | 第三階段 | 使用變長參數計算:1 |
sum(1, 2, 3) | 方法 B (int, int...) | 第三階段 | 使用變長參數計算:6 |
sum(1, new int[]{2,3}) | 方法 B (int, int...) | 第三階段 | 使用變長參數計算:6 |
sum(int... nums)IntStream.of(nums).sum() 替代手寫求和void foo(int... nums) {}
void foo(int[] nums) {} // 編譯錯誤:擦除後簽名相同
// 但調用時:
foo(1, 2, 3); // 調用可變參數版本
foo(new int[]{1,2}); // 調用陣列版本 (若單獨存在)
foo((int[]) null); // 調用陣列版本
foo(null); // 編譯歧義錯誤
Java 重載解析的「固定參數優先於可變參數」規則,體現了語言設計者對向後相容性與最小驚訝原則的堅持:早期代碼無可變參數概念,引入可變參數時必須確保舊調用行為不變。掌握三階段解析機制,是 Java 開發者從「能用」進階到「精通」的關鍵門檻之一。