成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

《java 8 實(shí)戰(zhàn)》讀書筆記 -第十章 用Optional取代null

時(shí)飛 / 771人閱讀

摘要:但返回的是一個(gè)類型的對(duì)象,這意味著操作的結(jié)果是一個(gè)類型的對(duì)象。反之,如果對(duì)象存在,這次調(diào)用就會(huì)將其作為函數(shù)的輸入,并按照與方法的約定返回一個(gè)對(duì)象。

一、Optional 類入門

Java 8中引入了一個(gè)新的類java.util.Optional。變量存在時(shí),Optional類只是對(duì)類簡(jiǎn)單封裝。變量不存在時(shí),缺失的值會(huì)被建模成一個(gè)“空”
的Optional對(duì)象,由方法Optional.empty()返回。

二、應(yīng)用 Optional 的幾種模式 1.創(chuàng)建 Optional 對(duì)象 (1) 聲明一個(gè)空的Optional

正如前文已經(jīng)提到,你可以通過靜態(tài)工廠方法Optional.empty,創(chuàng)建一個(gè)空的Optional對(duì)象:

Optional optCar = Optional.empty();
(2) 依據(jù)一個(gè)非空值創(chuàng)建Optional

你還可以使用靜態(tài)工廠方法Optional.of,依據(jù)一個(gè)非空值創(chuàng)建一個(gè)Optional對(duì)象:

Optional optCar = Optional.of(car); 

如果car是一個(gè)null,這段代碼會(huì)立即拋出一個(gè)NullPointerException,而不是等到你試圖訪問car的屬性值時(shí)才返回一個(gè)錯(cuò)誤。

(3) 可接受null的Optional

最后,使用靜態(tài)工廠方法Optional.ofNullable,你可以創(chuàng)建一個(gè)允許null值的Optional對(duì)象:

Optional optCar = Optional.ofNullable(car); 

如果car是null,那么得到的Optional對(duì)象就是個(gè)空對(duì)象。

Optional提供了一個(gè)get方法用于獲取Optional變量中的值,不過get方法在遭遇到空的Optional對(duì)象時(shí)也會(huì)拋出異常,所以不按照約定的方式使用它,又會(huì)讓我們?cè)俣认萑胗蒼ull引起的代碼維護(hù)的夢(mèng)魘。
2.使用 map 從 Optional 對(duì)象中提取和轉(zhuǎn)換值

比如,你可能想要從insurance公司對(duì)象中提取公司的名稱。提取名稱之前,你需要檢查insurance對(duì)象是否為null,代碼如下所示:

String name = null; 
if(insurance != null){ 
 name = insurance.getName(); 
}

用Optional實(shí)現(xiàn):

Optional optInsurance = Optional.ofNullable(insurance); 
Optional name = optInsurance.map(Insurance::getName);

原理示意:

3.使用 flatMap 鏈接 Optional 對(duì)象
Optional optPerson = Optional.of(person); 
Optional name = 
 optPerson.map(Person::getCar) //編譯無法通過
 .map(Car::getInsurance) 
 .map(Insurance::getName); 

不幸的是,這段代碼無法通過編譯。為什么呢?optPerson是Optional類型的變量, 調(diào)用map方法應(yīng)該沒有問題。但getCar返回的是一個(gè)Optional類型的對(duì)象,這意味著map操作的結(jié)果是一個(gè)Optional>類型的對(duì)象。因此,它對(duì)getInsurance的調(diào)用是非法的,因?yàn)樽钔鈱拥膐ptional對(duì)象包含了另一個(gè)optional對(duì)象的值,而它當(dāng)然不會(huì)支持getInsurance方法。
正確做法:

public String getCarInsuranceName(Optional person) { 
 return person.flatMap(Person::getCar) 
 .flatMap(Car::getInsurance) 
 .map(Insurance::getName) //Insurance::getName返回的是String類型,不是Optional
//返回的Optional可能是兩種情況:如果調(diào)用鏈上的任何一個(gè)
//方法返回一個(gè)空的Optional,那么結(jié)果就為空,否則返回的值就是你期望的保險(xiǎn)公司的名稱。
 .orElse("Unknown"); 
}

在域模型中使用Optional,以及為什么它們無法序列化
由于Optional類設(shè)計(jì)時(shí)就沒特別考慮將其作為類的字段使用,所以它也并未實(shí)現(xiàn)Serializable接口。
如果你一定要實(shí)現(xiàn)序列化的域模型,作為替代方案,我們建議你像下面這個(gè)例子那樣,提供一個(gè)能訪問聲明為Optional、變量值可能缺失的接口,代碼清單如下:

public class Person { 
 private Car car; 
 public Optional getCarAsOptional() { 
 return Optional.ofNullable(car); 
 } 
}
4. 默認(rèn)行為及解引用 Optional 對(duì)象

Optional類提供了多種方法讀取Optional實(shí)例中的變量值。

get()是這些方法中最簡(jiǎn)單但又最不安全的方法。如果變量存在,它直接返回封裝的變量值,否則就拋出一個(gè)NoSuchElementException異常。

orElse(T other)是我們?cè)诖a清單10-5中使用的方法,正如之前提到的,它允許你在Optional對(duì)象不包含值時(shí)提供一個(gè)默認(rèn)值。

orElseGet(Supplier other)是orElse方法的延遲調(diào)用版,Supplier方法只有在Optional對(duì)象不含值時(shí)才執(zhí)行調(diào)用。如果創(chuàng)建默認(rèn)值是件耗時(shí)費(fèi)力的工作,你應(yīng)該考慮采用這種方式(借此提升程序的性能),或者你需要非常確定某個(gè)方法僅在Optional為空時(shí)才進(jìn)行調(diào)用,也可以考慮該方式(這種情況有嚴(yán)格的限制條件)。

orElseThrow(Supplier exceptionSupplier)和get方法非常類似,它們?cè)庥鯫ptional對(duì)象為空時(shí)都會(huì)拋出一個(gè)異常,但是使用orElseThrow你可以定制希望拋出的異常類型。

ifPresent(Consumer)讓你能在變量值存在時(shí)執(zhí)行一個(gè)作為參數(shù)傳入的方法,否則就不進(jìn)行任何操作

5.以不解包的方式組合兩個(gè)Optional對(duì)象
public Insurance findCheapestInsurance(Person person, Car car) { 
 // 不同的保險(xiǎn)公司提供的查詢服務(wù)
 // 對(duì)比所有數(shù)據(jù)
 return cheapestCompany; 
}
public Optional nullSafeFindCheapestInsurance( 
 Optional person, Optional car) { 
 return person.flatMap(p -> car.map(c -> findCheapestInsurance(p, c))); 
}

這段代碼中,你對(duì)第一個(gè)Optional對(duì)象調(diào)用flatMap方法,如果它是個(gè)空值,傳遞給它的Lambda表達(dá)式不會(huì)執(zhí)行,這次調(diào)用會(huì)直接返回一個(gè)空的Optional對(duì)象。反之,如果person對(duì)象存在,這次調(diào)用就會(huì)將其作為函數(shù)Function的輸入,并按照與flatMap方法的約定返回一個(gè)Optional對(duì)象。這個(gè)函數(shù)的函數(shù)體會(huì)對(duì)第二個(gè)Optional對(duì)象執(zhí)行map操作,如果第二個(gè)對(duì)象不包含car,函數(shù)Function就返回一個(gè)空的Optional對(duì)象,整個(gè)nullSafeFindCheapestInsuranc方法的返回值也是一個(gè)空的Optional對(duì)象。最后,如果person和car對(duì)象都存在,作為參數(shù)傳遞給map方法的Lambda表達(dá)式能夠使用這兩個(gè)值安全地調(diào)用原始的findCheapestInsurance方法,完成期望的操作。

6.使用 filter 剔除特定的值
Optional optInsurance = ...; 
optInsurance.filter(insurance -> 
 "CambridgeInsurance".equals(insurance.getName())) 
 .ifPresent(x -> System.out.println("ok"));

filter方法接受一個(gè)謂詞作為參數(shù)。如果Optional對(duì)象的值存在,并且它符合謂詞的條件,
filter方法就返回其值;否則它就返回一個(gè)空的Optional對(duì)象。
Optional類的方法:

三、使用 Optional 的實(shí)戰(zhàn)示例 1.基礎(chǔ)類型的Optional對(duì)象

與 Stream對(duì)象一樣,Optional也提供了類似的基礎(chǔ)類型——OptionalInt、OptionalLong以及OptionalDouble,如果Stream對(duì)象包含了大量元素,出于性能的考量,使用基礎(chǔ)類型是不錯(cuò)的選擇,但對(duì)Optional對(duì)象而言,這個(gè)理由就不成立了,因?yàn)镺ptional對(duì)象最多只包含一個(gè)值。我們不推薦大家使用基礎(chǔ)類型的Optional,因?yàn)榛A(chǔ)類型的Optional不支持map、flatMap以及filter方法,而這些卻是Optional類最有用的方法。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74313.html

相關(guān)文章

  • java 8 實(shí)戰(zhàn)讀書筆記 -第十三章 函數(shù)式的思考

    摘要:當(dāng)我們希望能界定這二者之間的區(qū)別時(shí),我們將第一種稱為純粹的函數(shù)式編程,后者稱為函數(shù)式編程。函數(shù)式編程我們的準(zhǔn)則是,被稱為函數(shù)式的函數(shù)或方法都只能修改本地變量。另一種觀點(diǎn)支持引用透明的函數(shù)式編程,認(rèn)為方法不應(yīng)該有對(duì)外部可見的對(duì)象修改。 一、實(shí)現(xiàn)和維護(hù)系統(tǒng) 1.共享的可變數(shù)據(jù) 如果一個(gè)方法既不修改它內(nèi)嵌類的狀態(tài),也不修改其他對(duì)象的狀態(tài),使用return返回所有的計(jì)算結(jié)果,那么我們稱其為純粹...

    Donne 評(píng)論0 收藏0
  • Java 8 函數(shù)式編程」讀書筆記——流

    摘要:本文是函數(shù)式編程第三章的讀書筆記,章名為流。正確使用表達(dá)式明確要達(dá)成什么轉(zhuǎn)化,而不是說明如何轉(zhuǎn)化沒有副作用只通過函數(shù)的返回值就能充分理解函數(shù)的全部作用函數(shù)不會(huì)修改程序或外界的狀態(tài)獲取值而不是變量避免使用數(shù)組逃過的追殺,應(yīng)該考慮優(yōu)化邏輯 本文是「Java 8 函數(shù)式編程」第三章的讀書筆記,章名為流。本章主要介紹了外部迭代與內(nèi)部迭代以及常用的高階函數(shù)。 外部迭代與內(nèi)部迭代 外部迭代 過去我...

    qpwoeiru96 評(píng)論0 收藏0
  • java 8 實(shí)戰(zhàn)讀書筆記 -第四章 引入流

    摘要:第四章引入流一什么是流流是的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合通過查詢語句來表達(dá),而不是臨時(shí)編寫一個(gè)實(shí)現(xiàn)。 第四章 引入流 一、什么是流 流是Java API的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合(通過查詢語句來表達(dá),而不是臨時(shí)編寫一個(gè)實(shí)現(xiàn))。就現(xiàn)在來說,你可以把它們看成遍歷數(shù)據(jù)集的高級(jí)迭代器。此外,流還可以透明地并行處理,你無需寫任何多線程代碼。 下面兩段代碼都是用來返回低...

    jeyhan 評(píng)論0 收藏0
  • 讀書筆記《重構(gòu) 改善既有代碼的設(shè)計(jì)》

    摘要:重構(gòu)在不改變代碼的外在的行為的前提下對(duì)代碼進(jìn)行修改最大限度的減少錯(cuò)誤的幾率本質(zhì)上,就是代碼寫好之后修改它的設(shè)計(jì)。重構(gòu)可以深入理解代碼并且?guī)椭业?。同時(shí)重構(gòu)可以減少引入的機(jī)率,方便日后擴(kuò)展。平行繼承目的在于消除類之間的重復(fù)代碼。 重構(gòu) (refactoring) 在不改變代碼的外在的行為的前提下 對(duì)代碼進(jìn)行修改最大限度的減少錯(cuò)誤的幾率 本質(zhì)上, 就是代碼寫好之后 修改它的設(shè)計(jì)。 1,書中...

    mdluo 評(píng)論0 收藏0
  • 【J2SE】java并發(fā)編程實(shí)戰(zhàn) 讀書筆記( 一、二、三章)

    摘要:發(fā)布的對(duì)象內(nèi)部狀態(tài)可能會(huì)破壞封裝性,使程序難以維持不變性條件。不變性線程安全性是不可變對(duì)象的固有屬性之一。可變對(duì)象必須通過安全方式來發(fā)布,并且必須是線程安全的或者有某個(gè)鎖保護(hù)起來。 線程的優(yōu)缺點(diǎn) 線程是系統(tǒng)調(diào)度的基本單位。線程如果使用得當(dāng),可以有效地降低程序的開發(fā)和維護(hù)等成本,同時(shí)提升復(fù)雜應(yīng)用程序的性能。多線程程序可以通過提高處理器資源的利用率來提升系統(tǒng)的吞吐率。與此同時(shí),在線程的使用...

    QLQ 評(píng)論0 收藏0
  • Java8實(shí)戰(zhàn)》-第三章讀書筆記(Lambda表達(dá)式-01)

    摘要:之前,使用匿名類給蘋果排序的代碼是的,這段代碼看上去并不是那么的清晰明了,使用表達(dá)式改進(jìn)后或者是不得不承認(rèn),代碼看起來跟清晰了。這是由泛型接口內(nèi)部實(shí)現(xiàn)方式造成的。 # Lambda表達(dá)式在《Java8實(shí)戰(zhàn)》中第三章主要講的是Lambda表達(dá)式,在上一章節(jié)的筆記中我們利用了行為參數(shù)化來因?qū)Σ粩嘧兓男枨?,最后我們也使用到了Lambda,通過表達(dá)式為我們簡(jiǎn)化了很多代碼從而極大地提高了我們的...

    longshengwang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<