不定長度引數


在呼叫方法時,若方法的引數個數事先無法決定該如何處理?例如System.out.printf()方法就無法事先決定引數個數:

System.out.printf("%d", 10);
System.out.printf("%d %d", 10, 20);
System.out.printf("%d %d %d", 10, 20, 30);

在JDK5之後支援不定長度引數(Variable-length Argument),可以輕鬆的解決這個問題。直接來看示範:

package cc.openhome;

public class MathTool {
    public static int sum(int... numbers) {
        int sum = 0;
        for(int number : numbers) {
            sum += number;
        }
        return sum;
    }
}

要使用不定長度引數,宣告參數列時要於型態關鍵字後加上...,在sum()方法可使用增強式for迴圈來取得不定長度引數中的每個元素,你可以如此使用:

System.out.println(MathTool.sum(1, 2));
System.out.println(MathTool.sum(1, 2, 3));
System.out.println(MathTool.sum(1, 2, 3, 4));

實際上不定長度引數是編譯器蜜糖,反編譯後就可以一窺究竟:

public static transient int sum(int ai[]) {
    int i = 0;
    int ai1[] = ai;
    int j = ai1.length;
    for(int k = 0; k < j; k++) {
        int l = ai1[k];
        i += l;
    }
    return i;
}

不定長度引數實際是展開為陣列,而呼叫不定長度引數的客戶端,例如System.out.println(MathTool.sum(1, 2, 3)),展開後也是變為陣列:

System.out.println(
    sum(new int[] {1, 2, 3})
);

因此,就算在JDK1.4之前,也可以使用陣列來解決引數個數無法確認的方法呼叫。

使用不定長度引數時,方法上宣告的不定長度參數必須是參數列最後一個。例如以下是合法宣告:

public void some(int arg1, int arg2, int... varargs) {
     ...
}

以下方式是不合法宣告:

public void some(int... varargs, int arg1, int arg2) {
     ...
}

使用兩個以上不定長度引數也是不合法的:

public void some(int... varargs1, int... varargs2) {
     ...
}

如果使用物件的不定長度引數,宣告的方法相同,例如:

public void some(Other... others) {
      ...
}