解析Java的可變長參數(shù)列表及其使用時(shí)的注意點(diǎn)
Java 可變參數(shù)列表
class A {}
由于所有的類都繼承于Object,可以以O(shè)bject數(shù)組為參數(shù)的方法:
public class parameter {
static void printArray(Object[] args){
for(Object obj : args){
System.out.print(obj + " ");
}
System.out.println();
}
public static void main(String[] args){
printArray(new Object[] {
new Integer(47), new Float(3.14), new Double(11.11)
});
printArray(new Object[]{"one", "two", "there"});
printArray(new Object[]{new A(), new A(), new A()});
}
}
對于Java SE5之后版本添加了特性可以如此寫:
public class parameter {
public static void printArray(Object... args){
for(Object obj : args){
System.out.print(obj + " ");
}
System.out.println();
}
public static void main(String[] args){
printArray(new Integer(47), new Float(3.14), new Double(11.11));
printArray(47, 3.14F, 11.11);
printArray("one", "two", "three");
printArray(new A(), new A(), new A());
printArray((Object[]) new Integer[]{1, 2, 3, 4});
printArray();
}
}
可以使用Object以為的參數(shù)列表:
public class VarargType{
static void f(Character... args){
System.out.print(args.getClass());
System.out.println(" length " + args.length);
}
static void g(int... args){
System.out.print(args.getClass());
System.out.println(" length " + args.length);
}
public static void main(String[] args){
f('a');
f();
g(1);
g();
System.out.println(" int [] " + new int[0].getClass());
}
}
這是 Java 5 引入的一個(gè)特性,如果一個(gè)方法要接收的參數(shù)數(shù)量是不確定的,那么這個(gè)特性就可以派上用場了。
比如,在涉及IO操作的地方,基本上至少需要關(guān)閉兩個(gè)流:輸入、輸出,我喜歡把流關(guān)閉的操作封裝成下面的方法,這樣只需一次調(diào)用就可以關(guān)閉多個(gè)流。
public static void closeSilent(Closeable... closeables) {
for (Closeable closeable : closeables) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ignored) {
}
}
}
}
這是我覺得這個(gè)特性唯一適合使用的地方,具備下面的特點(diǎn):
這些參數(shù)具有相同的類型;
參數(shù)數(shù)量不確定,每一個(gè)都是可選的;
這些參數(shù)的用途都是一樣的,比如上面都是執(zhí)行關(guān)閉。
Java 可變長參數(shù)列表只能放在方法參數(shù)列表的最后。
Java可變長參數(shù)列表的實(shí)現(xiàn)
Java可變長參數(shù)列表的實(shí)現(xiàn)是通過編譯器把把這些參數(shù)封裝成一個(gè)數(shù)組來傳遞的。
比如上面的方法的簽名實(shí)際上是: closeSilent(Closeable[] closeables) void 。
踩坑
有個(gè)方法,被 A、B 兩個(gè)地方 A、B 調(diào)用,9 月,在 A 這里需要增加一個(gè)參數(shù),當(dāng)時(shí)腦子一抽瘋,決定用可變長參數(shù)列表,覺得 B 那里不用改簡單點(diǎn),坑就這樣埋下了。
最近要求 B 這里要新增兩個(gè)參數(shù),那就在方法的參數(shù)列表里繼續(xù)加參數(shù),這些參數(shù)的類型是不同的,所以可變長參數(shù)列表聲明成 Object 類型的。
第一個(gè)坑就是在這個(gè)方法內(nèi)取可變長參數(shù)的元素時(shí),沒考慮到有的參數(shù)是沒傳的,直接爆數(shù)組越位的異常了。馬上就覺得可變長參數(shù)列表的不好了,那就不用了唄,改為常規(guī)的固定形式的參數(shù)傳遞。
改完之后,在測試環(huán)境測了都沒問題。把生產(chǎn)環(huán)境的幾個(gè)類替換之后,結(jié)果卻報(bào)錯(cuò)了,方法找不到,一看方法簽名,還是數(shù)組的,沒有替換到。從源碼看,那個(gè)調(diào)用的地方不需要更改,所以沒想到要替換;由于測試環(huán)境是全量打包,所以不會(huì)出現(xiàn)問題。
方法的簽名是在編譯的時(shí)候就確定了的,源碼層面看起來不需要改的不表示編譯后的類也不需要替換了。
其實(shí)以前也聽到過,在這種發(fā)包不規(guī)范的情況下,把源碼里的一個(gè)常量值改了之后,只替換了這個(gè)定義常量的類文件,沒有把所有引用這個(gè)常量的類文件重新編譯替換,導(dǎo)致出現(xiàn)莫名其妙的問題。跟方法簽名的情況本質(zhì)上是一樣的問題。
相關(guān)文章
springboot使用shiro-整合redis作為緩存的操作
這篇文章主要介紹了springboot使用shiro-整合redis作為緩存的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
玩轉(zhuǎn)spring boot 結(jié)合jQuery和AngularJs(3)
玩轉(zhuǎn)spring boot,這篇文章主要介紹了結(jié)合jQuery和AngularJs,玩轉(zhuǎn)spring boot,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
基于springMvc+hibernate的web application的構(gòu)建
下面小編就為大家?guī)硪黄趕pringMvc+hibernate的web application的構(gòu)建。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10
Spring security如何重寫Filter實(shí)現(xiàn)json登錄
這篇文章主要介紹了Spring security 如何重寫Filter實(shí)現(xiàn)json登錄,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
詳解Spring Boot實(shí)戰(zhàn)之單元測試
本篇文章主要介紹了詳解Spring Boot實(shí)戰(zhàn)之單元測試,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07

