前一個小節已大致介紹過如何定義方法,這個小節要再來看看如何在方法上定義參數、返回值,如何使用方法重載,並看看 JDK 5.0 中新增的不定長度引數( Variable-Length Argument )要如何使用。
在 Java 中定義方法(Method)的基本語法如下所示:
[modifier] type identifier(type param, ...) { [return data;] }
其中:
程式碼 11-1 的第 12 行到第 15 行示範過不返回值、不接受參數的 hello()方法:
public void hello() { System.out.print("Hello "); System.out.println(name); }
第 17 行到第 19 行則示範了不返回值、具有 String 型態參數的方法:
public void setName(String one) { name = one; }
參數列上的參數宣告,其作用與變數宣告相同,如果宣告的是基本型態參數,則呼叫方法時所給定的引數,會複製一份給參數;如果參數宣告時是物件型態,則宣告的參數作用是參考至物件,呼叫方法時所給定的物件,會被參數參考。
可以使用程式碼 11-3 來作個檢驗:
public class MethodDemo{ public void primitiveParam(int para){ para = 10; } public void referParam(int[] array){ array[0] = 10; } public static void main(String[] args){ int x = 5; int[] array = {1, 2, 3, 4, 5}; MethodDemo demo = new MethodDemo(); demo.primitiveParam(x); demo.referParam(array); System.out.println("x: " + x); System.out.print("array: "); for (int element : array){ System.out.print(element); System.out.print(" "); } System.out.println(); } }程式碼 11-3 MethodDemo.java
您可以從圖 11-5 的執行結果看到,在呼叫 primitiveParam() 方法時,在方法中將 para 設定為 10,並不會影響 x 的值,這是因為 x 的值被複製一份給 para,而傳遞陣列物件時,參數 array 與 main 中的 array 參考的是同一物件,所以您在referParam()中改變索引 0 位置的元素,最後在 main 顯示出來的陣列元素也會受影響:
程式碼 11-4 提供一個具有返回值,有兩個參數的方法示範,作用是利用輾轉相除法計算並傳回兩個數的最大公因數:
public class GCDFinder{ public int gcdOf(int m, int n){ int r; while (n != 0){ r = m % n; m = n; n = r; } return m; } public static void main(String[] args){ int a = Integer.parseInt(args[0]); int b = Integer.parseInt(args[1]); GCDFinder finder = new GCDFinder(); System.out.println(a + ", " + b + " 最大公因數: " + finder.gcdOf(a, b)); } }程式碼 11-4 GCDFinder.java
程式碼中第 18 行會將 a、b 的值分別複製一份給 m 與 n,而返回值也是將 m 複製一份再返回,一個執行的結果範例如下所示:
在定義方法時,有時候只是參數個數或是參數型態不同,但是方法的執行目的是一致的,這時候您可以為方法取相同的名稱,編譯器會自動依參數個數或型態來判斷您所呼叫的是哪一個方法。
舉個例子來說,在上一個單元中介紹過的 StringBuilder 類別,在進行字串附加的 append()方法,其實有多個版本:
圖11-8 StringBuilder 的 append()方法具有多個版本
像這樣依參數個數或引數型態不同,但允許方法具有同一個名稱的機制稱之為重載( Overloading ),要注意的是,實際呼叫方法時,您所給定的引數個數及引數型態,將作為判斷哪一個方法該被呼叫執行的依據。
要注意的是,返回值的型態並不作為方法重載的依據,所以類似於以下的程式碼片段是無法通過編譯的:
public int doSomething1() { return 1; } public double doSomething1() { return 1.0; }
在 JDK 5.0 之前,參數的個數必須事先決定,然而有時您在設計方法時,並無法決定使用該方法的開發人員要傳遞多少引數給方法來使用,例如執行加總的 sumOf()方法,開發人員也許會希望它可以接受 3 個參數、4 個參數 5 個參數或更多的參數。
從 JDK 5.0 開始方法的參數設定上開始支援不定長度引數( Variable-Length Argument ),只要在宣告參數時,於型態指定後加上...即可,程式碼 11-5 直接以實例示範不定長度引數的使用。
public class SimpleAdder{ public int sumOf(int... params){ int sum = 0; for (int i = 0; i < params.length; i++){ sum = sum + params[i]; } return sum; } public static void main(String[] args){ SimpleAdder adder = new SimpleAdder(); System.out.print("1+2+3="); System.out.print("1+2+3+4="); System.out.print("1+2="); System.out.println(adder.sumOf(1, 2)); System.out.println(adder.sumOf(1, 2, 3)); System.out.println( adder.sumOf(1, 2, 3, 4)); } }程式碼 11-5 SimpleAdder.java
從程式碼中的第 4 行到第 6 行可以看到,被宣告的不定長度引數 params,實際上被轉換為陣列,這是在編譯時期由編譯器為您作的轉換動作,在 sumOf()方法中要使用陣列存取的方法來取得呼叫方法時所提供的引數。執行結果如下所示:
重點提示
在 JDK 5.0 之前面對不定長度引數的需求時,使用陣列先收集好引數,再將整個陣列傳遞給方法,也正是解決需求的方案之一。
在方法上設定不定長度引數時,記得必須設定在引數列的最後一個,例如下面的方式是合法的:
public void someMethod( int arg1, int arg2, int... varargs) { // .... }
但下面的方式是不合法的:
public void someMethod( int... varargs, int arg1, int arg2) { // .... }
您也沒辦法設定兩個以上的不定長度引數,理由很簡單,編譯器無法決定引數的長度各是為何,例如下面的方式是不合法的:
public void someMethod( int... varargs1, int... varargs2) { // .... }