前言
在寫方法時,我們有時候會使用到相同型別,但參數個數不同的時候,就會使用到多載(Overloading)或是傳入陣列解決問題。
當需要 1個、2個和3個相同型別參數時,使用多載可以解決;使用陣列在操作上就顯得有點麻煩。
public double average(int x1, int x2){...};
public double average(int x1, int x2, int x3){...};
當100個相同型別參數時,使用多載就必須要寫100個方法,萬一之後要修改,也要修改100個方法,這...太累人了!
所以,使用參數傳入陣列可以省事多了!只是每一次要使用前都要先建立陣列。
當如果要使用 1 ~ 20 個相同型別參數時,該使用多載還是使用陣列呢?這時可以考慮使用可變動參數的寫法,擁有相同型別但數量不同的參數。
一、可變動參數的規定
1.1) | 只有用於方法的宣告 |
1.2) | 宣告時若有多個參數,必須把可變動參數的語法宣告在最後一個參數。 |
1.3) | 可變動參數的宣告,其功能與陣列相同。 |
宣告上的差異
public double average(int[] x){...};
呼叫上的差異
int[] p = new int{10,20,30,40};
double avg = average(p);
範例 1:操作可變動式參數
範例 2:可變動式參數換成一維陣列
範例 3:使用 int[]... ,可以傳入很多個一維陣列的可變動式參數
int[]... 可以使用 int[][] 替換。
二、多個參數中使用變動式參數
2.1 宣告時若有多個參數,必須把可變動參數的語法宣告在最後一個參數,且只能使用一次變動式參數。
編譯錯誤 1:變動式參數不是在最後一個
TestVarLenArg1.java:6: error: ')' expected public void show(int... x, String str){ ^ TestVarLenArg1.java:6: error: ';' expected public void show(int... x, String str){ ^ 2 errors
編譯錯誤 2:變動式參數有兩個
TestVarLenArg2.java:6: error: ')' expected public void show(int... x, String... str){ ^ TestVarLenArg2.java:6: error: <identifier> expected public void show(int... x, String... str){ ^ TestVarLenArg2.java:6: error: <identifier> expected public void show(int... x, String... str){ ^ 3 errors
2.2 避免帶有可變動參數的方法多載(Overloading)
成功執行 1:如果能與固定和可變動參數的方法匹配時,優先使用固定參數的方法。
編譯錯誤 3:編譯器不知道該選哪一個方法
TestVarLenArg4.java:4: error: reference to show is ambiguous obj.show("hello"); ^ both method show(String,String...) in TestVarLenArg4 and method show(String...) in TestVarLenArg4 match TestVarLenArg4.java:5: error: reference to show is ambiguous obj.show("hello", "Ethan"); ^ both method show(String,String...) in TestVarLenArg4 and method show(String...) in TestVarLenArg4 match 2 errors
2.3 別讓 null 值和空值威脅到可變動參數的方法
編譯錯誤 4:只有一個參數的方法,相當於後方都是空值;String 與 Integer 物件初始值都可以是 null。
TestVarLenArg5.java:4: error: reference to show is ambiguous obj.show("hello"); ^ both method show(String,String...) in TestVarLenArg5 and method show(String,Integer...) in TestVarLenArg5 match TestVarLenArg5.java:5: error: reference to show is ambiguous obj.show("hello", null); ^ both method show(String,String...) in TestVarLenArg5 and method show(String,Integer...) in TestVarLenArg5 match TestVarLenArg5.java:5: warning: non-varargs call of varargs method with inexact argument type for last parameter; obj.show("hello", null); ^ cast to String for a varargs call cast to String[] for a non-varargs call and to suppress this warning 2 errors 1 warning
這裡隱藏了實際參數類型,這是很不好的編碼習慣。不僅僅調用者需要"猜測"該調用哪個方法,而且被調用者也可能產生內部邏輯混亂。對於「編譯錯誤 4」而言,應該做如下的修改:
TestVarLenArg5 obj = new TestVarLenArg5();
String[] strArr = null;
obj.show("hello", strArr);
}
2.4 覆寫(Override)有變動式參數或陣列的方法時,不隨意改變參數形式
TestVarLenArg6.java:24: error: show(String...) in Base is defined in an inaccessible class or interface sub.show("hello"); ^ 1 error
第一個能編譯通過,這是為什麼呢?事實上,base 參考物件變數把子類別物件實例 new Sub() 做了向上轉型,參考物件變數是由父類別決定的,當然能通過。而看看子類別直接調用的情況,這時編譯器看到子類別覆寫了父類別的 show() 方法,因此肯定使用子類別重新定義的 show() 方法,儘管參數不匹配也無法訪問父類別的方法。
2.5 底下這個範例,是有陷阱的唷!您知道輸出結果是什麼嗎?
三、總結
變動式參數只有用於方法的宣告。
宣告時若有多個參數,必須把可變動參數的語法宣告在最後一個參數,且只能使用一次變動式參數。
避免帶有可變動參數的方法多載(Overloading),注意使用的原則。
別讓 null 值和空值威脅到可變動參數的方法,使用明確的參數型態,而不使用隱式。
覆寫(Override)有變動式參數或陣列的方法時,不隨意改變參數形式。
使用變動式參數時,其功能與陣列相同。
沒有留言:
張貼留言