java.util.Optional

簡介

爲了避免null導致NullPointerException,JAVA8新增了Optional來避免這種情況的發生。

當變量T存在時, Optional類只是對類簡單封裝。當變量T不存在時,缺失的值會被建模成一個“空”的Optional對象,由方法Optional.empty()返回。

 null引用和Optional.empty()有什麼本質的區別嗎?從語義上,可以把它們當作一回事兒,但是實際中它們之間的差別非常大:如果嘗試引用一個null, 一定會觸發NullPointerException,而Optional.empty()則沒這個問題,它是Optional類的一個有效對象,多種場景都能正常調用。

但如果你就是不使用Optional,那麼可以理解爲你是允許該對象爲null。

String name;按照JAVA8約定,這種形式的變量是不允許出現null情況的,如果出現null,則只能說是業務流程出現問題。

Optional<String> name;按照JAVA8約定,這種形式的變量是允許出現null情況的。

方法使用案例

Optional<Car> optCar = Optional.empty();聲明一個空的Optional

Optional<Car> optCar = Optional.of(car);依據一個非空值創建Optional

Optional<Car> optCar = Optional.ofNullable(car);可接受null的Optional

Optional<Insurance> optInsurance = Optional.ofNullable(insurance);

Optional<String> name = optInsurance.map(Insurance::getName);可以把Optional對象看成一種特殊的集合數據,它至多包含一個元素。如果Optional包含一個值,那函數就將該值作爲參數傳遞給map,對該值進行轉換。如果Optional爲空,就什麼也不做。使用 map 來從Optional對象中提取和轉換值

person.flatMap(Person::getCar).flatMap(Car::getInsurance).map(Insurance::getName).orElse("Unknown");flatMap方法接受一個函數作爲參數,這個函數的返回值是另一個流。這個方法會應用到流中的每一個元素,最終形成一個新的流的流。但是flagMap會用流的內容替換每個新生成的流。換句話說,由方法生成的各個流會被合併或者扁平化爲一個單一的流。

optInsurance.filter(insurance->"CambridgeInsurance".equals(insurance.getName())).ifPresent(x->System.out.println("ok"));filter方法接受一個謂詞作爲參數。 如果Optional對象的值存在,並且它符合謂詞的條件,filter方法就返回其值;否則它就返回一個空的Optional對象。如果你還記得我們可以將Optional看成最多包含一個元素的Stream對象,這個方法的行爲就非常清晰了。 如果Optional對象爲空,它不做任何操作,反之,它就對Optional對象中包含的值施加謂詞操作。如果該操作的結果爲true,它不做任何改變,直接返回該Optional對象,否則就將該值過濾掉,將Optional的值置空。

常用方法API

①get()是這些方法中最簡單但又最不安全的方法。如果變量存在,它直接返回封裝的變量

值,否則就拋出一個NoSuchElementException異常。所以,除非你非常確定Optional變量一定包含值,否則使用這個方法是個相當糟糕的主意。此外,這種方式即便相對於嵌套式的null檢查,也並未體現出多大的改進。

②orElse(T other)允許在Optional對象不包含值時提供一個默認值。

③orElseGet(Supplier<? extends T> other)是orElse方法的延遲調用版, Supplier

方法只有在Optional對象不含值時才執行調用。如果創建默認值是件耗時費力的工作,

應考慮採用這種方式,或者需要非常確定某個方法僅在Optional爲空時才進行調用,也可以考慮該方式。

④orElseThrow(Supplier<? extends X> exceptionSupplier)和get方法非常類似,它們遭遇Optional對象爲空時都會拋出一個異常,但是使用orElseThrow可以定製希望拋出的異常類型。

⑤ifPresent(Consumer<? super T>)能在變量值存在時執行一個作爲參數傳入的方法,否則就不進行任何操作。

API列表

1.empty:返回一個空的Optional實例。

2.filter:如果值存在並且滿足提供的謂詞,就返回包含該值的 Optional對象;否則返回一個空的Optional對象。

3.flatMap:如果值存在,就對該值執行提供的mapping函數調用,返回一個Optional類型的值,否則就返回一個空的Optional對象。

4.get:如果該值存在,將該值用Optional封裝返回,否則拋出一個NoSuchElementException異常。

5.ifPresent:如果值存在,就執行使用該值的方法調用,否則什麼也不做。

6.isPresent:如果值存在就返回true,否則返回false。

7.map:如果值存在,就對該值執行提供的mapping函數調用。

8.of:將指定值用Optional封裝之後返回,如果該值爲null,則拋出一個NullPointerException異常。

9.ofNullable:將指定值用Optional封裝之後返回,如果該值爲null,則返回一個空的Optional對象。

10.orElse:如果有值則將其返回,否則返回一個默認值。

11.orElseGet:如果有值則將其返回,否則返回一個由指定的 Supplier接口生成的值。

12.orElseThrow:如果有值則將其返回,否則拋出一個由指定的 Supplier接口生成的異常。

改造老舊代碼

Null轉Optional:

Optional<Object> value =

Optional.ofNullable(map.get("key"));

處理異常:

try {

return Optional.of(Integer.parseInt(s));

} catch (NumberFormatException e) {

return Optional.empty();

}

注意事項

①Optional也提供了類似的基礎類型:OptionalInt、 OptionalLong以及OptionalDouble。但是這些基礎類型卻不支持map、flatMap以及filter方法。

②Optional對象無法由基礎類型的Optional組合構成,比如:OptionalInt類型的對象,你就不能將其作爲方法引用傳遞給另一個Optional對象的flatMap方法。

③Optional類並未實現Serializable接口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章