Tips
書中的源代碼地址:https://github.com/jbloch/effective-java-3e-source-code
注意,書中的有些代碼裏方法是基於Java 9 API中的,因此JDK 最好下載 JDK 9以上的版本。java
看到相似這樣的方法並不罕見: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