過多的使用null可能會致使大量的bugs,Google code 底層代碼中,95%的集合類默認不接受null值。對null值,使用快速失敗拒絕null比默認接受更好。數組
另外,null自己的含義很模糊。例如,對於null返回值,如Map.get(key)返回null,可能由於和key對應的值爲null,也可能map中根本沒有該key。null也能夠用以表示失敗或成功,可能表明任何事物。使用其餘值而不是null可使代碼含義表達的更清楚。工具
儘管如此,有些地方仍是應該使用null。在內存和速度方面,null是廉價的,而且在對象數組中是不可避免的。spa
基於以上緣由,Guava大部分工具對null都設計爲快速失敗。另外,Guava提供了一些方便使用null的工具。設計
不要在Set中使用null,也不要將null做爲Map的key值,使用特殊值代替null可讓查找的語義更清晰。code
若是你想把null做爲Map的value,更好的辦法不是將該條目放入Map中,而是應該以一個單獨的Set維護「值爲null」的鍵集合。由於Map中某個鍵對應的值爲null和Map中沒有某個鍵值很容易混淆。對象
若是須要在List中使用null,而且這個List是稀疏的,則使用Map<Integer, E>可能更好。blog
若是確實須要null,但null值不能和Guava的集合一塊兒工做,則只能選擇其餘方式,如JDK中的Collections.unmodifiableList代替Guava中的ImmutableList。內存
Guava設計Optional來解決null問題,Optional<T>表示可能爲null的T類型的引用。Optional實例要麼包含一個非null的引用,要麼什麼都不包含(absent),從不會包含null值引用。在須要使用null的時候,能夠用Optional代替。ci
Optional除了賦予null意義外,增長可讀性,還在於它是一種傻瓜式的防禦。Optional 迫使你積極思考引用確實的狀況,由於你必須顯式地從Optional 獲取引用。get
Optional 的可能應用方面:
Optional.of(T) | 建立指定引用的Optional實例,對null值拋出NullPointException。建議直接傳遞常量參數。 |
Optional.absent() | 建立引用缺失的Optional實例 |
Optional.fromNullable(T) | 建立指定引用的Optional實例,若引用爲null則表示缺失 |
assertEquals("training", Optional.of("training").get()); Optional<String> optionalName = Optional.absent(); assertFalse(optionalName.isPresent()); // Non-null instance Optional<String> optionalName = Optional.fromNullable("bob"); assertEquals("bob", optionalName.get()); // null instance assertSame(Optional.absent(), Optional.fromNullable(null));
boolean isPresent() | 若是該Optional 包含非null引用,返回true。 |
T get() | 返回Optional 所包含的引用,若引用缺失,則拋出IllegalStateException。 |
T or(T) | 返回Optional 所包含的引用,若引用缺失,返回默認值。 |
T orNull() | 返回Optional 所包含的引用,若引用缺失,返回null。 |
Set<T> asSet() | 返回Optional所包含的singleton不可變集合,若爲空,返回空集合。 |
public void testIsPresent_no() { assertFalse(Optional.absent().isPresent()); } public void testIsPresent_yes() { assertTrue(Optional.of("training").isPresent()); } public void testGet_absent() { Optional<String> optional = Optional.absent(); try { optional.get(); fail(); } catch (IllegalStateException expected) { } } public void testGet_present() { assertEquals("training", Optional.of("training").get()); } public void testOr_T_present() { assertEquals("a", Optional.of("a").or("default")); } public void testOr_T_absent() { assertEquals("default", Optional.absent().or("default")); } public void testOrNull_present() { assertEquals("a", Optional.of("a").orNull()); } public void testOrNull_absent() { assertNull(Optional.absent().orNull()); } public void testAsSet_present() { Set<String> expected = Collections.singleton("a"); assertEquals(expected, Optional.of("a").asSet()); } public void testAsSet_absent() { assertTrue("Returned set should be empty", Optional.absent().asSet().isEmpty()); } public void testAsSet_presentIsImmutable() { Set<String> presentAsSet = Optional.of("a").asSet(); try { presentAsSet.add("b"); fail(); } catch (UnsupportedOperationException expected) { } } public void testAsSet_absentIsImmutable() { Set<Object> absentAsSet = Optional.absent().asSet(); try { absentAsSet.add("foo"); fail(); } catch (UnsupportedOperationException expected) { } }