Java 5 引入可變參數,語法:型別 ... 參數名。本質上是陣列語法糖,呼叫端可傳 0~N 個引數或直接傳陣列。
public class VarArgsDemo {
// 1. 基本型別
public static void printInts(int... nums) {
for (int n : nums) System.out.print(n + " ");
System.out.println();
}
// 2. 參考型別
public static void printStrings(String... strs) {
for (String s : strs) System.out.print(s + " ");
System.out.println();
}
// 3. 自訂類別
static class User { String name; int age; User(String n, int a){name=n;age=a;} }
public static void printUsers(User... users) {
for (User u : users) System.out.println(u.name + "\t" + u.age);
}
public static void main(String[] args) {
printInts(1, 2, 3);
printInts(new int[]{4,5,6}); // 也可傳陣列
printStrings("A", "B");
printUsers(new User("張三",25), new User("李四",24));
}
}
| 規則 | 說明 |
|---|---|
| 位置固定 | 可變參數必須是最後一個參數 |
| 唯一性 | 每個方法最多只能有一個可變參數 |
| 重載優先序 | 固定參數 > 可變參數。foo(int i) 優於 foo(int... i) |
| 型別擦除 | 編譯後簽名為 foo(int[]),反射可用 isVarArgs() 判斷 |
| 自動裝箱 | printInts(1,2) 會自動裝箱為 Integer[] 若簽名為 Integer... |
printInts(); // 內部 nums 為長度 0 陣列,非 null
printInts((int[])null); // 內部 nums 為 null,foreach 會拋 NPE
方法內建議防禦:
if (nums == null) return; // 或 nums = new int[0];
void foo(Object... args) {}
void foo(String... args) {} // 編譯錯誤:呼叫 foo("a") 模糊
避免為相容型別分別定義可變參數重載。
<T> void bar(T... items) {} // 編譯警告:unchecked generic array creation
加上 @SafeVarargs(Java 7+)抑制警告,但需確保方法不將參數陣列存儲或暴露給外部。
foo(int a), foo(int a, int b), foo(int... rest))。String.format, Arrays.asList)。List<String> list = Arrays.asList("a", "b", "c");
printStrings(list.toArray(new String[0])); // 陣列傳入
// 或 Java 8+ Stream
list.forEach(VarArgsDemo::printStrings); // 需適配單參數版本
可變參數讓 API 更靈活、呼叫端更簡潔。牢記「最後一個、唯一一個、固定參數優先」,並注意 null 安全與重載模糊。高頻場景提供固定參數重載以避免陣列分配開銷。善用 @SafeVarargs 搭配不可變操作,寫出既優雅又安全的 API。