更新時間:2020-06-01 16:30:48 來源:動力節點 瀏覽2175次
在Java5中提供了變長參數(varargs),也就是在方法定義中可以使用個數不確定的參數,對于同一方法可以使用不同個數的參數調用,例如print("hello");print("hello","lisi");print("hello","張三","alexia");下面介紹如何定義可變長參數以及如何使用可變長參數。
1.可變長參數的定義
使用...表示可變長參數,例如
print(String...?args){
??...
}
在具有可變長參數的方法中可以把參數當成數組使用,例如可以循環輸出所有的參數值。
print(String...?args){
???for(String?temp:args)
??????System.out.println(temp);
}
2.可變長參數的方法的調用
調用的時候可以給出任意多個參數也可不給參數,例如:
print();
print("hello");
print("hello","lisi");
print("hello","張三",?"alexia")
3.可變長參數的使用規則
(1)在調用方法的時候,如果能夠和固定參數的方法匹配,也能夠與可變長參數的方法匹配,則選擇固定參數的方法。看下面代碼的輸出:
package?com;
//?這里使用了靜態導入
import?static?java.lang.System.out;
public?class?VarArgsTest?{
????public?void?print(String...?args)?{
????????for?(int?i?=?0;?i?<?args.length;?i++)?{
????????????out.println(args[i]);
????????}
????}
????public?void?print(String?test)?{
????????out.println("----------");
????}
????public?static?void?main(String[]?args)?{
????????VarArgsTest?test?=?new?VarArgsTest();
????????test.print("hello");
????????test.print("hello",?"alexia");
????}
}
(2)如果要調用的方法可以和兩個可變參數匹配,則出現錯誤,例如下面的代碼:
package?com;
//?這里使用了靜態導入
import?static?java.lang.System.out;
public?class?VarArgsTest1?{
????public?void?print(String...?args)?{
????????for?(int?i?=?0;?i?<?args.length;?i++)?{
????????????out.println(args[i]);
????????}
????}
????public?void?print(String?test,String...args?){
??????????out.println("----------");
????}
????public?static?void?main(String[]?args)?{
????????VarArgsTest1?test?=?new?VarArgsTest1();
????????test.print("hello");
????????test.print("hello",?"alexia");
????}
}
對于上面的代碼,main方法中的兩個調用都不能編譯通過,因為編譯器不知道該選哪個方法調用,如下所示:
(3)一個方法只能有一個可變長參數,并且這個可變長參數必須是該方法的最后一個參數
以下兩種方法定義都是錯誤的。
public void test(String...strings,ArrayList list){
}
public void test(String...strings,ArrayList...list){
}
4.可變長參數的使用規范
(1)避免帶有可變長參數的方法重載:如3.1中,編譯器雖然知道怎么調用,但人容易陷入調用的陷阱及誤區
(2)別讓null值和空值威脅到變長方法,如3.2中所示,為了說明null值的調用,重新給出一個例子:
package?com;public?class?VarArgsTest1?{
????public?void?print(String?test,?Integer...?is)?{??
????}
????public?void?print(String?test,String...args?){??????
????}
????public?static?void?main(String[]?args)?{
????????VarArgsTest1?test?=?new?VarArgsTest1();
????????test.print("hello");
????????test.print("hello",?null);
????}
}
因為兩個方法都匹配,編譯器不知道選哪個,于是報錯了,這里同時還有個非常不好的編碼習慣,即調用者隱藏了實參類型,這是非常危險的,不僅僅調用者需要“猜測”該調用哪個方法,而且被調用者也可能產生內部邏輯混亂的情況。對于本例來說應該做如下修改:
public?static?void?main(String[]?args)?{
????VarArgsTest1?test?=?new?VarArgsTest1();
????String[]?strs?=?null;
?????test.print("hello",?strs);
?}
(3)覆寫變長方法也要循規蹈矩
下面看一個例子,大家猜測下程序能不能編譯通過:
package?com;
public?class?VarArgsTest2?{
????/**
?????*?@param?args
?????*/
????public?static?void?main(String[]?args)?{
????????//?TODO?Auto-generated?method?stub
????????//?向上轉型
????????Base?base?=?new?Sub();
????????base.print("hello");
????????
????????//?不轉型
????????Sub?sub?=?new?Sub();
????????sub.print("hello");
????}
}
//?基類
class?Base?{
????void?print(String...?args)?{
????????System.out.println("Base......test");
????}
}
//?子類,覆寫父類方法
class?Sub?extends?Base?{
????@Override
????void?print(String[]?args)?{
????????System.out.println("Sub......test");
????}
}
答案當然是編譯不通過,是不是覺得很奇怪?
第一個能編譯通過,這是為什么呢?事實上,base對象把子類對象sub做了向上轉型,形參列表是由父類決定的,當然能通過。而看看子類直接調用的情況,這時編譯器看到子類覆寫了父類的print方法,因此肯定使用子類重新定義的print方法,盡管參數列表不匹配也不會跑到父類再去匹配下,因為找到了就不再找了,因此有了類型不匹配的錯誤。
這是個特例,覆寫的方法參數列表竟然可以與父類不相同,這違背了覆寫的定義,并且會引發莫名其妙的錯誤。
這里,總結下覆寫必須滿足的條件:
最后,給出一個有陷阱的例子,大家應該知道輸出結果:
package?com;
public?class?VarArgsTest?{
????public?static?void?m1(String?s,?String...?ss)?{
????????for?(int?i?=?0;?i?<?ss.length;?i++)?{
????????????System.out.println(ss[i]);
????????}
????}
????public?static?void?main(String[]?args)?{
????????m1("");
????????m1("aaa");
????????m1("aaa",?"bbb");
????}
}
以上就是動力節點java培訓機構的小編針對“Javaweb系統視頻之架構演變”的內容進行的回答,希望對大家有所幫助,如有疑問,請在線咨詢,有專業老師隨時為你服務。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習