Effective Java 第三版——54. 返回空的數組或集合不要返回null

Tips
書中的源代碼地址:https://github.com/jbloch/effective-java-3e-source-code
注意,書中的有些代碼裏方法是基於Java 9 API中的,因此JDK 最好下載 JDK 9以上的版本。java

Effective Java, Third Edition

54. 返回空的數組或集合不要返回null

看到相似這樣的方法並不罕見:git

// 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);
}

沒有理由對沒有奶酪(Cheese)可供購買的狀況進行特殊處理。這樣須要在客戶端作額外的代碼處理可能爲null的返回值,例如:程序員

List<Cheese> cheeses = shop.getCheeses();
if (cheeses != null && cheeses.contains(Cheese.STILTON))
    System.out.println("Jolly good, just the thing.");

在幾乎每次使用返回null來代替空集合或數組的方法時,都須要使用這種迂迴的方式。 它容易出錯,由於編寫客戶端的程序員可能忘記編寫特殊狀況代碼來處理null返回。 多年來這種錯誤可能會被忽視,由於這種方法一般會返回一個或多個對象。 此外,返回null代替空容器會使返回容器的方法的實現變得複雜。github

有時有人認爲,null返回值比空集合或數組更可取,由於它避免了分配空容器的開銷。這個論點有兩點是不成立的。首先,除非測量結果代表所討論的分配是性能問題的真正緣由,不然不宜擔憂此級別的性能(條目67)。第二,能夠在不分配空集合和數組的狀況下返回它們。下面是返回可能爲空的集合的典型代碼。一般,這就是你所須要的:數組

//The right way to return a possibly empty collection
public List<Cheese> getCheeses() {
    return new ArrayList<>(cheesesInStock);
}

若是有證據代表分配空集合會損害性能,能夠經過重複返回相同的不可變空集合來避免分配,由於不可變對象能夠自由共享(條目17)。下面的代碼就是這樣作的,使用了Collections.emptyList方法。若是你要返回一個Set,可使用Collections.emptySet;若是要返回Map,則使用Collections.emptyMap。可是請記住,這是一個優化,不多須要它。若是你認爲你須要它,測量一下先後的性能表現,確保它確實有幫助:性能

// Optimization - avoids allocating empty collections
public List<Cheese> getCheeses() {
    return cheesesInStock.isEmpty() ? Collections.emptyList()
        : new ArrayList<>(cheesesInStock);
}

數組的狀況與集合的狀況相同。 永遠不要返回null,而是返回長度爲零的數組。 一般,應該只返回一個正確長度的數組,這個長度可能爲零。 請注意,咱們將一個長度爲零的數組傳遞給toArray方法,以指示所需的返回類型,即Cheese []優化

//The right way to return a possibly empty array
public Cheese[] getCheeses() {
    return cheesesInStock.toArray(new Cheese[0]);
}

若是你認爲分配零長度數組會損害性能,則能夠重複返回相同的零長度數組,由於全部零長度數組都是不可變的:this

// Optimization - avoids allocating empty arrays

private static final Cheese[] EMPTY_CHEESE_ARRAY = new Cheese[0];

public Cheese[] getCheeses() {
    return cheesesInStock.toArray(EMPTY_CHEESE_ARRAY);

}

在優化的版本中,咱們將相同的空數組傳遞到每一個toArray調用中,當cheesesInStock爲空時,這個數組將從getCheeses返回。不要爲了提升性能而預先分配傳遞給toArray的數組。研究代表,這樣作會拔苗助長[Shipilev16]:code

// Don’t do this - preallocating the array harms performance!

return cheesesInStock.toArray(new Cheese[cheesesInStock.size()]);

總之,永遠不要返回null來代替空數組或集合。它使你的API更難以使用,更容易出錯,而且沒有性能優點。orm

相關文章
相關標籤/搜索