String... argsString[]String[] argsnullnull 情況// 源碼
public void varargs(String... args) { for (String s : args) {} }
public void array(String[] args) { for (String s : args) {} }
// 編譯後 (javap -c)
public void varargs(String[] args) { ... } // 簽名相同!
public void array(String[] args) { ... }
結論:JVM 層面無區別,差異僅在編譯期語法糖與調用端體驗。
| 場景 | 可變參數 | 陣列參數 |
|---|---|---|
| 零引數 | method() ✅ | method(new String[]{}) 或 method(null) |
| 單引數 | method("a") ✅ | method(new String[]{"a"}) |
| 多引數 | method("a","b","c") ✅ | method(new String[]{"a","b","c"}) |
| 已有陣列 | method(arr) ✅ | method(arr) ✅ |
| 混合固定+可變 | method(true, "a", "b") ✅ | method(true, new String[]{"a","b"}) |
(String fixed, String... args) ✅,(String... args, String fixed) ❌(String... a, int... b) ❌args.length、args[0]、增強 for 迴圈皆可用method("a") 匹配 (String s) 而非 (String... args)| 語言 | 機制 | 範例 |
|---|---|---|
| Java | 可變參數 ... | void method(String... args) |
| C# | params 關鍵字 | void Method(params string[] args) |
| C# | 預設參數值 | void Method(bool flag, string content = "", int count = 1) |
| Kotlin | 預設參數 + vararg | fun method(flag: Boolean, vararg args: String, count: Int = 1) |
Java 無預設參數值,可變參數是唯一簡化調用的語法糖。
String.join(",", "a", "b", "c")String.format("%s=%d", "age", 18)List.of("a", "b", "c")、Arrays.asList()fireEvent("click", data1, data2)method(String arg) + method(String[] args)method(String[] args, int start, int end)| 陷阱 | 現象 | 解決 |
|---|---|---|
| 可變參數重載模糊 | method(Object...) 和 method(String...) 調用 method("a") 編譯錯誤 | 避免同名方法不同可變參數類型重載 |
| null 傳遞歧義 | method((String[])null) vs method((String)null) | 顯式轉型或避免 null 傳遞 |
| 修改參數陣列影響調用端 | 可變參數傳入現有陣列時,方法內修改會影響原陣列 | 防御性複製 args = args.clone() 或用 List |
| 遞歸傳遞可變參數 | recursive(args) 每層複製陣列 | 改用索引或 List |
String... args 是 String[] args 的編譯期語法糖,JVM 層面無差異。核心價值在於調用端體驗:支援 0~N 引數、混合固定參數、語法簡潔。掌握重載解析優先級、唯一可變參數限制、防御性複製等細節,能避免常見陷阱,寫出更優雅的 API。