main(String[] args) 到自訂 print(String... msgs)Java 5 引入可變參數,本質是「編譯器自動包裝陣列」的語法糖。掌握其規則與限制,能寫出更靈活的 API(如 String.format、Arrays.asList、日誌框架)。
... 置於型別與變數名之間:int... nums 或 int ...nums 均可。nums.length、nums[i]、增強 for 迴圈。// 1. 基礎求和:固定參數 + 可變參數
public static int add(int first, int... rest) {
int sum = first;
for (int n : rest) sum += n;
return sum;
}
add(2,3); // 5
add(2,3,5); // 10
add(2); // 2 (rest 為空陣列)
// 2. 純可變參數
public static void test(String... args) {
System.out.println("數量:" + args.length);
for (String s : args) System.out.println(s);
}
test("1","2","3"); // 印出 3 行
test(); // 數量:0,無輸出
test(new String[]{"a","b"}); // 直接傳陣列也合法
| 陷阱 | 原因 | 對策 |
|---|---|---|
| 重載模糊 | foo(int...) vs foo(int[]) 無法共存;foo(String, int...) vs foo(String, int, int...) 呼叫 foo("a",1) 編譯器不知選哪個 | 避免同名方法同時有可變參數與陣列/多參數重載;必要時改用不同方法名 |
| NullPointerException | 呼叫 method(null) 時,編譯器無法判斷是傳 null 陣列還是單一 null 元素 | 明確轉型:method((String[])null) 或 method((String)null);方法內檢查 args==null |
| 效能誤區 | 頻繁呼叫隱含建立陣列物件,熱路徑可能有壓力 | 極度敏感路徑改用固定參數或預建陣列複用;一般業務碼無感 |
| 堆疊追蹤混淆 | 可變參數方法在堆疊顯示為陣列型別,除錯時需注意 | 習慣即可,無實質影響 |
泛型可變參數會產生「unchecked」警告(因陣列協變性導致型別安全漏洞)。若方法內不將參數陣列存入可見欄位、不暴露給外部、不做型別轉換,可加 @SafeVarargs 抑制警告(Java 9+ 也可用於 private 方法)。
@SafeVarargs
public static <T> List<T> asList(T... elements) { ... } // JDK 內部即如此標註