在本文中,您將借助示例來(lái)學(xué)習(xí)Java中的可變參數(shù)(Varargs)。您還將學(xué)習(xí)何時(shí)使用varargs,何時(shí)不使用它們。
假設(shè)您正在創(chuàng)建Java方法。但是,您不確定您的方法將接受多少個(gè)參數(shù)。為了解決這個(gè)問(wèn)題,Java 1.5引入了varargs。
Varargs是變量參數(shù)的縮寫。 在Java中,方法的參數(shù)可以接受任意數(shù)量的值。 可以接受可變數(shù)量的值的該參數(shù)稱為varargs。
實(shí)現(xiàn) varargs 的語(yǔ)法如下:
accessModifier methodName(datatype… arg) { // 方法主體 }
為了定義vararg,在方法的形參中使用……(三個(gè)點(diǎn))。
接受可變數(shù)量參數(shù)的方法稱為可變數(shù)量方法,或簡(jiǎn)稱為varargs方法。
首先,讓我們看一下不使用varargs的示例:
class NoVararg { public int sumNumber(int a, int b){ return a+b; } public int sumNumber(int a, int b, int c){ return a+b+c; } public static void main( String[] args ) { NoVararg obj = new NoVararg(); System.out.println(obj.sumNumber(1, 2)); System.out.println(obj.sumNumber(1, 2, 3)); } }
當(dāng)您運(yùn)行該程序時(shí),輸出將是:
3 6
正如您看到的,必須重載sumNumber()方法才能使其適用于3個(gè)參數(shù)。
如果用戶要添加5個(gè)數(shù)字或10或100,該怎么辦?
使用varargs可以以一種簡(jiǎn)潔的方式處理這一問(wèn)題。讓我們看一個(gè)代碼示例:
class VarargExample { public int sumNumber(int ... args){ System.out.println("參數(shù)長(zhǎng)度: " + args.length); int sum = 0; for(int x: args){ sum += x; } return sum; } public static void main( String[] args ) { VarargExample ex = new VarargExample(); int sum2 = ex.sumNumber(2, 4); System.out.println("sum2 = " + sum2); int sum3 = ex.sumNumber(1, 3, 5); System.out.println("sum3 = " + sum3); int sum4 = ex.sumNumber(1, 3, 5, 7); System.out.println("sum4 = " + sum4); } }
運(yùn)行該程序時(shí),輸出為:
參數(shù)長(zhǎng)度: 2 sum2 = 6 參數(shù)長(zhǎng)度: 3 sum3 = 9 參數(shù)長(zhǎng)度: 4 sum4 = 16
在這里,sumNumber()方法返回傳遞給它的int參數(shù)的總和(與傳遞的參數(shù)數(shù)量無(wú)關(guān))。
正如您看到的,varargs在某些情況下非常有用。但是,如果您確定傳遞給方法的參數(shù)數(shù)量,請(qǐng)改用方法重載。例如,如果您確定sumNumber()方法僅用于計(jì)算2個(gè)或3個(gè)參數(shù)的總和,請(qǐng)像第一個(gè)示例一樣使用重載。
讓我們?cè)倥e一個(gè)實(shí)例。Java庫(kù)中定義的format()方法接受varargs。在JDK中,format()方法定義如下:
public static String format(Locale l, String format, Object... args) { // body }
class Company { public static void main(String[] args) { String siteName = "(cainiaoplus.com)"; int empCount = 6; String type = "教程網(wǎng)站"; System.out.println( String.format( "Site Name : %s, Emp Count: %d Type: %s", siteName, empCount, type ) ); } }
運(yùn)行該程序時(shí),輸出為:
Site Name : (cainiaoplus.com), Emp Count: 6 Type: 教程網(wǎng)站
讓我們看以下偽代碼:
public int sumNumber(int ... nums) { // 方法主體 }
... 語(yǔ)法告訴Java編譯器可以使用零個(gè)或多個(gè)參數(shù)來(lái)調(diào)用該方法。 結(jié)果,nums變量被隱式聲明為int []類型的數(shù)組。 因此,在方法內(nèi)部,使用數(shù)組語(yǔ)法訪問(wèn)nums變量。
如果沒(méi)有參數(shù),則長(zhǎng)度nums為0。
與典型方法類似,您可以重載vararg方法。
class VarargOverload { private void test(int ... args){ int sum = 0; for (int i: args) { sum += i; } System.out.println("sum = " + sum); } private void test(boolean p, String ... args){ boolean negate = !p; System.out.println("negate = " + negate); System.out.println("args.length = "+ args.length); } public static void main( String[] args ) { VarargOverload obj = new VarargOverload(); obj.test(1, 2, 3); obj.test(true, "hello", "world"); } }
運(yùn)行該程序時(shí),輸出為:
sum = 6 negate = false args.length = 2
在上面的程序中,test()方法通過(guò)更改其接受的參數(shù)數(shù)量而重載。
這是使用Java Varargs時(shí)應(yīng)記住的幾件事:
1.在定義方法簽名時(shí),請(qǐng)務(wù)必保留最后varargs。
變量參數(shù)必須是傳遞給方法的最后一個(gè)參數(shù)??紤]一下,您調(diào)用了如下doSomething()方法:
doSomething(1, 2, 3, 4);
并且,您的doSomething()方法定義為:
//錯(cuò)誤的方法聲明 public void doSomething(int ... nums, int p){ // method body }
在這種情況下,編譯器無(wú)法確定傳遞給nums的參數(shù)數(shù)量。
但是,如果將方法定義為:
public void doSomething(int p, int ... nums) { // method body }
Java編譯器將第一個(gè)參數(shù)分配給 p,其余int參數(shù)分配給 nums。
2.一種方法只能有一個(gè)varargs參數(shù)。
例如,此方法聲明不正確:
int doSomething(int p, float ... floatNums, double ... doubleNums) { // code }
讓我們看一下這樣的重載test()方法:
class Demo { static void test(int ... vargs) { // method body } static void test(int n, int ... vargs) { // method body } }
在上面的程序中,即使您嘗試調(diào)用test()方法,即使test()方法已重載并且接受不同數(shù)量的參數(shù),編譯器也會(huì)感到困惑。
編譯器不知道調(diào)用哪個(gè)方法。編譯器可能會(huì)認(rèn)為,您正在嘗試test(int ... vargs)使用一個(gè)varargs參數(shù)進(jìn)行調(diào)用。同樣,編譯器可能會(huì)認(rèn)為,您正在嘗試test(int n, int ... vargs)使用傳遞給第一個(gè)參數(shù)的參數(shù)調(diào)用,而第二個(gè)參數(shù)為空。
由于存在兩種可能性,因此會(huì)引起歧義。因此,有時(shí)您可能需要使用兩個(gè)不同的方法名稱,而不是重載varargs方法。