概念
JDK5增加了可變參數(shù)方法(variable arity method)
可變參數(shù)方法接受0個(gè)或多個(gè)指定類型的參數(shù)。
可變參數(shù)機(jī)制:先創(chuàng)建一個(gè)數(shù)組媳瞪,數(shù)組大小為調(diào)用位置所傳遞的參數(shù)數(shù)量因谎,然后將參數(shù)值傳遞到數(shù)組中亏推,最后將數(shù)組傳遞給方法敛瓷。
問題的提出
編寫需要一個(gè)或多個(gè)某種類型參數(shù)的方法叁巨,而不是需要零個(gè)或多個(gè)參數(shù)。例如求多個(gè)int
參數(shù)的最小值琐驴》郑可變參數(shù)方法不適合這種場景秤标。
問題:如果客戶端調(diào)用這個(gè)方式時(shí)绝淡,沒有傳遞參數(shù),會(huì)在運(yùn)行時(shí)而不是編譯時(shí)失敳越牢酵;代碼不美觀。必須對args
進(jìn)行顯示的有效性檢查衙猪,除非將min
初始化為Integer.MAX_VALUE
,否則無法使用for-each循環(huán)馍乙。
問題的解決辦法
聲明該方法帶有兩個(gè)參數(shù),一個(gè)是指定類型的正常參數(shù)垫释,另一個(gè)是這種類型的varargs參數(shù)丝格。
可變參數(shù)的適用場景
當(dāng)真正需要一個(gè)方法帶有不定數(shù)量的參數(shù)時(shí),可變參數(shù)就非常有效棵譬。
可變參數(shù)是為printf
而設(shè)計(jì)的显蝌,它是在jdk5引入的。
printf
和反射機(jī)制都從可變參數(shù)中獲得極大的收益订咸。
錯(cuò)誤的例子 Arrays.asList
增強(qiáng)為可使用可變參數(shù)
可以將以final
數(shù)組作為參數(shù)的方法曼尊,改造成可變參數(shù)版本。但是不應(yīng)該這么做脏嚷。
Arrays.asList方法不是設(shè)計(jì)用來將多個(gè)參數(shù)集中到一個(gè)列表中的骆撇。
上面打印數(shù)組內(nèi)容的方法只在對象引用類型的數(shù)組上才有用。
在JDK5之前父叙,Arrays.asList()在基本類型的數(shù)組上用將無法編譯神郊。
現(xiàn)在的版本呢?
通過對比趾唱,可以發(fā)現(xiàn)屿岂,傳入基本數(shù)據(jù)類型的數(shù)組也是可以通過編譯的,但是運(yùn)行這個(gè)程序鲸匿,會(huì)輸出無意義的結(jié)果爷怀。
Arrays.asList方法將int類型的數(shù)組的引用集中到單個(gè)元素?cái)?shù)組中,并封裝成List<int[]>带欢。
將數(shù)組轉(zhuǎn)變?yōu)樽址?code>Arrays.asList已經(jīng)過時(shí)了运授。Arrays
類有專門將任何類型的數(shù)組轉(zhuǎn)變?yōu)樽址姆椒ā?/p>
//The right way to print an array
System.out.println(Arrays.toString(digits));
如果不改造Arrays.asList
烤惊,更好的辦法是給Collections
添加一個(gè)新的方法,專門用來將它的參數(shù)集中到列表中吁朦。
這種方法可以提供收集功能柒室,而不會(huì)危及對現(xiàn)有Arrays.asList
方法的類型檢查。
不必改造具有final
數(shù)組參數(shù)的每個(gè)方法逗宜;只當(dāng)確實(shí)是在數(shù)量不定的值上執(zhí)行調(diào)用時(shí)才使用可變參數(shù)雄右。
可變參數(shù)的性能問題
每次調(diào)用可變參數(shù)方法都會(huì)進(jìn)行一次數(shù)組分配和初始化。
解決辦法——重載:
假設(shè)確定對某個(gè)方法95%的調(diào)用會(huì)有3個(gè)或者更少的參數(shù)纺讲,就聲明該方法的5個(gè)重載擂仍,每個(gè)重載方法帶有0至3個(gè)普通參數(shù),當(dāng)參數(shù)的數(shù)目超過3個(gè)時(shí)熬甚,就使用一個(gè)可變參數(shù)方法逢渔。
所有的調(diào)用只有5%參數(shù)數(shù)量超過3個(gè)的調(diào)用需要?jiǎng)?chuàng)建數(shù)組。
EnumSet
類對它的靜態(tài)工廠使用了這種方法乡括,最大限度地減少創(chuàng)建枚舉集合的成本肃廓,枚舉集合為位域提供在性能方面有競爭性的代替方法。