ITEM 54: RETURN EMPTY COLLECTIONS OR ARRAYS, NOT NULLS
??常見的方法是這樣的:
// Returns null to indicate an empty collection. Don't do this!
private final List<Cheese> cheesesInStock = ...;
/**
* @return a list containing all of the cheeses in the shop,
* or null if no cheeses are available for purchase.
*/
public List<Cheese> getCheeses() {
return cheesesInStock.isEmpty() ? null : new ArrayList<>(cheesesInStock);
}
??沒有理由對(duì)沒有 Cheese 可供購買的情況進(jìn)行特殊處理。這樣做需要額外的代碼在客戶端處理可能的空返回值掰茶,例如:
List<Cheese> cheeses = shop.getCheeses();
if (cheeses != null && cheeses.contains(Cheese.STILTON))
System.out.println("Jolly good, just the thing.");
??在幾乎每次使用返回 null 來代替空集合或數(shù)組的方法時(shí)冯乘,都需要使用這種繞圈子的方法恕洲。它很容易出錯(cuò),因?yàn)榫帉懣蛻魴C(jī)的程序員可能忘記編寫處理 null 返回的特殊情況代碼图焰。這樣的錯(cuò)誤可能會(huì)被忽略多年启盛,因?yàn)檫@樣的方法通常返回一個(gè)或多個(gè)對(duì)象。此外,在空容器中返回 null 會(huì)使返回容器的方法的實(shí)現(xiàn)復(fù)雜化僵闯。
??有人認(rèn)為卧抗,空返回值比空集合或數(shù)組更可取,因?yàn)樗苊饬朔峙淇杖萜鞯拈_銷鳖粟。這個(gè)論點(diǎn)有兩點(diǎn)是站不住腳的社裆。
??首先,在這個(gè)級(jí)別上擔(dān)心性能是不明智的向图,除非度量結(jié)果表明有問題的分配確實(shí)會(huì)導(dǎo)致性能問題(item 67)泳秀。其次,可以返回空的集合和數(shù)組而不分配它們榄攀。下面是返回可能為空的集合的典型代碼嗜傅。通常,這就是你所需要的:
//The right way to return a possibly empty collection
public List<Cheese> getCheeses() {
return new ArrayList<>(cheesesInStock);
}
??在不太可能的情況下檩赢,有證據(jù)表明分配空集合會(huì)損害性能吕嘀,您可以通過重復(fù)返回相同的不可變空集合來避免分配,因?yàn)椴豢勺儗?duì)象可以自由共享(item 17)贞瞒。下面是使用 Collections.emptyList() 完成此任務(wù)的方法偶房。如果你返回一個(gè) Set,你應(yīng)當(dāng) 使用 Collections.emptySet() ; 如果你要返回一個(gè) Map 军浆,你會(huì)使用Collections.emptyMap() 棕洋。但是請(qǐng)記住,這是一個(gè)優(yōu)化瘾敢,很少需要它拍冠。如果你認(rèn)為你需要它尿这,衡量前后的表現(xiàn)簇抵,以確保它確實(shí)有幫助:
// Optimization - avoids allocating empty collections
public List<Cheese> getCheeses() {
return cheesesInStock.isEmpty() ? Collections.emptyList() : new ArrayList<>(cheesesInStock);
}
??數(shù)組的情況與集合的情況相同。不要返回 null射众,而要返回零長度的數(shù)組碟摆。通常,您應(yīng)該簡單地返回一個(gè)長度正確的數(shù)組叨橱,它可能是零典蜕。注意,我們將一個(gè)零長度的數(shù)組傳遞到toArray方法中罗洗,以指示所需的返回類型愉舔,即 Cheese[]:
//The right way to return a possibly empty array
public Cheese[] getCheeses() {
return cheesesInStock.toArray(new Cheese[0]);
}
??如果你認(rèn)為分配零長度數(shù)組會(huì)損害性能,你可以重復(fù)返回相同的零長度數(shù)組伙菜,因?yàn)樗械牧汩L度數(shù)組都是不可變的:
// Optimization - avoids allocating empty arrays
private static final Cheese[] EMPTY_CHEESE_ARRAY = new Cheese[0];
public Cheese[] getCheeses() {
return cheesesInStock.toArray(EMPTY_CHEESE_ARRAY);
}
??在優(yōu)化的版本中轩缤,我們將相同的空數(shù)組傳遞到每個(gè)toArray調(diào)用中,當(dāng)cheesesInStock 為空時(shí),這個(gè)數(shù)組將從 getCheeses 返回火的。
??不要為了提高性能而預(yù)先分配傳遞給 toArray 的數(shù)組壶愤。研究表明,它是適得其反(Shipile?v16):
// Don’t do this - preallocating the array harms performance!
return cheesesInStock.toArray(new Cheese[cheesesInStock.size()]);
??總之,永遠(yuǎn)不要用null來代替空數(shù)組或集合馏鹤。它使您的API更難于使用征椒,更容易出錯(cuò),并且沒有性能優(yōu)勢湃累。