GUAVA--基礎工具(Optional)

一、使用和避免 null

1.一、避免

Null 的含糊語義讓人很不舒服。Null 不多能夠明確地表示某種語義,例如,Map.get(key)返回 Null時,可能表示 map 中的值是 null,亦或 map 中沒有 key 對應的值。Null 能夠表示失敗、成功或幾乎任何狀況。使用 Null 之外的特定值,會讓你的邏輯描述變得更清晰。java

Null 確實也有合適和正確的使用場景,如在性能和速度方面 Null 是廉價的,並且在對象數組中,出現 Null 也是沒法避免的。但相對於底層庫來講,在應用級別的代碼中,Null 每每是致使混亂,疑難問題和模糊語義的元兇,就如同咱們舉過的 Map.get(key)的例子。最關鍵的是,Null 自己沒有定義它表達的意思。數組

從官方文檔中能夠總結出爲何有時候要避免使用null的緣由:工具

  • Null的意義含糊、不明顯。
  • Null 自己沒有定義它表達的意思。

null能夠表示空指針、空對象、甚至初始化爲null,從人的思惟角度上去想,確實能明白null在各場景的意義,可是對於計算機而言null是多種意義,難以區分的。就如上述例子「Map.get(key)返回 Null時,可能表示 map 中的值是 null,亦或 map 中沒有 key 對應的值」。性能

鑑於這些緣由,不少 Guava 工具類對 Null 值都採用快速失敗操做,除非工具類自己提供了針對 Null 值的因變措施。此外,Guava 還提供了不少工具類,讓你更方便地用特定值替換 Null 值。google

1.二、使用

考慮一下使用天然的 null 對象——特殊值。舉例來講,爲某個 enum 類型增長特殊的枚舉值表示 null,好比 java.math.RoundingMode 就定義了一個枚舉值 UNNECESSARY,它表示一種不作任何舍入操做的模式,用這種模式作舍入操做會直接拋出異常。 若是你真的須要使用 null 值,可是 null 值不能和 Guava 中的集合實現一塊兒工做,你只能選擇其餘實現。.net

使用null的方法:將意義混淆的null用一個表明null的參數代替。指針


二、Optional

大多數狀況下,開發人員使用 null 代表的是某種缺失情形:多是已經有一個默認值,或沒有值,或找不到值。例如,Map.get 返回 null 就表示找不到給定鍵對應的值。 Guava 用 Optional表示可能爲 null 的 T 類型引用。一個 Optional 實例可能包含非 null 的引用(咱們稱之爲引用存在),也可能什麼也不包括(稱之爲引用缺失)。它從不說包含的是 null 值,而是用存在或缺失來表示。但Optional 從不會包含 null 值引用。code

2.一、java.util.Optional 和 com.google.common.base.Optional

java.util.Optional是java8的新特性。orm

  1. Optional 類是一個能夠爲null的容器對象。若是值存在則isPresent()方法會返回true,調用get()方法會返回該對象。
  2. Optional 是個容器:它能夠保存類型T的值,或者僅僅保存null。Optional提供不少有用的方法,這樣咱們就不用顯式進行空值檢測。
  3. Optional 類的引入很好的解決空指針異常。

其實從以上3點能夠看出,不管是對null判斷返回true和false仍是解決空指針異常問題,其實都是減小 null 判斷以及 NullPointerException 的異常發生,儘可能減小直接對null的判斷。對象

Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5

2.二、建立Optional

2.2.一、建立Optional實例
方法類型 方法名 描述
static <T> Optional<T> Optional.of(T reference) 若引用爲null則快速失敗 拋出異常java.lang.NullPointerException
static <T> Optional<T> Optional.absent() 建立引用缺失的Optional實例
static <T> Optional<T> Optional.fromNullable(T nullableReference) 若是 nullableReference 非null,返回包含該引用的Optional實例,不然返回 absent().
static <T> @Nullable Optional<T> Optional.fromJavaUtil(java.util.Optional<T>) 返回給定的java.util.Optional,等效com.google.common.base.Optional值,若是參數爲null,則返回null
static <T> Iterable<T> Optional.presentInstances(Iterable<? extends Optional<? extends T>> optionals) 從提供的選項中返回每一個當前實例的值,按順序跳過absent()的出現次數
static <T> Optional<T> Optional.toJavaUtil(com.google.common.base.Optional<T>) 返回給定com.google.common.base.Optional的等效java.util.Optional值,若是參數爲null,則返回null
2.2.二、實例方法
方法類型 方法名 描述 備註
abstract Set<T> asSet() 返回一個不可變的單集的惟一元素所包含的實例(若是存在),不然爲一個空的不可變的集合 asSet返回的是一個不可變的set集合,若是對這個set集合作增刪改的操做會拋異常
abstract boolean equals(@Nullable Object object) 返回boolean,object是一個Optional實例,而且所包含的引用彼此相等或都不存在 與常見得Object的equals是一樣用法
abstract T get() 返回所包含的實例,該實例必須存在 返回包含在Optional內實例
abstract int hashCode() 返回此實例的哈希碼 返回此實例的哈希碼
abstract boolean isPresent() 返回true此持有者是否包含(非空)實例。 Optional內的實例存在返回true,不然false
abstract Optional<T> or(Optional<? extends T> secondChoice) Optional若是存在值,則返回此值;secondChoice除此之外 若是Optional中有實例則返回實例,不然返回secondChoice
abstract T or(Supplier<? extends T> supplier) 返回包含的實例(若是存在);supplier.get()除此之外 若是Optional中有實例則返回實例,不然返回supplier.get()
abstract T or(T defaultValue) 返回包含的實例(若是存在);defaultValue除此之外 若是Optional中有實例則返回實例,不然返回defaultValue
abstract T orNull() 返回包含的實例(若是存在);null除此之外 若是Optional中有實例則返回實例,不然返回null
static <T> Iterable<T> toJavaUtil() 返回與java.util.Optional此可選值的等效值 其實是調用了java.util.Optional.ofNullable,返回Optional<T>
abstract <V> Optional<V> transform(Function<? super T,V> function) 若是實例存在,則使用給定的實例進行轉換Function;不然, absent()返回 判斷function是否爲null,是則返回null,不是調用toJavaUtil()
2.2.三、舉例說明
import com.google.common.base.Optional;

public class GuavaTest {

	public static void main(String args[]) {
		GuavaTest demo = new GuavaTest();

        Integer value1 = null;
        Integer value2 = new Integer(10);

        // Optional.fromNullable:容許參數爲null.
        Optional<Integer> a = Optional.fromNullable(value1);
        // Optional.of:若是參數爲null,則拋出NullPointerException
        Optional<Integer> b = Optional.of(value2);

        System.out.println(demo.sum(a, b));
    }

    public Integer sum(Optional<Integer> a, Optional<Integer> b) {
        // Optional.isPresent:檢查值是否存在
        System.out.println("第一個參數是否存在: " + a.isPresent());
        System.out.println("第二個參數是否存在: " + b.isPresent());

        // Optional.or:若是存在則返回值,不然返回傳遞的默認值
        Integer value1 = a.or(new Integer(0));

        // Optional.get:獲取值,此時有值存在
        Integer value2 = b.get();

        return value1 + value2;
    }

}

三、小結

根據2.2.2的實例方法的描述和備註,2.2.3的例子不難看出整個Optional都是爲了服務於null的處理,例如設置一個默認值,Optional是作一個數據保護的做用,在可能出現空指針的地方對數據的一個數據處理,主要是對null的處理。

相關文章
相關標籤/搜索