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

資訊專欄INFORMATION COLUMN

Java 8th 函數(shù)式編程:Optional 類型

RayKr / 3522人閱讀

摘要:當(dāng)滿足條件時(shí)執(zhí)行傳入的參數(shù)化操作。最后提醒一點(diǎn),好用但不能濫用,在設(shè)計(jì)一個(gè)接口方法時(shí)是否采取類型返回需要斟酌,一味的使用會(huì)讓代碼變得比較啰嗦,反而破壞了代碼的簡潔性。鑒于作者水平有限,文中不免有錯(cuò)誤之處,歡迎批評(píng)指正個(gè)人博客

NullPointException 可以說是所有 java 程序員都遇到過的一個(gè)異常,雖然 java 從設(shè)計(jì)之初就力圖讓程序員脫離指針的苦海,但是指針確實(shí)是實(shí)際存在的,而 java 設(shè)計(jì)者也只能是讓指針在 java 語言中變得更加簡單、易用,而不能完全的將其剔除,所以才有了我們?nèi)粘K姷降年P(guān)鍵字 null。

空指針異常是一個(gè)運(yùn)行時(shí)異常,對(duì)于這一類異常,如果沒有明確的處理策略,那么最佳實(shí)踐在于讓程序早點(diǎn)掛掉,但是很多場(chǎng)景下不是開發(fā)人員沒有具體的處理策略,而是根本沒有意識(shí)到空指針異常的存在。當(dāng)異常真的發(fā)生的時(shí)候,處理策略也很簡單,在存在異常的地方添加一個(gè) if 語句判定即可,但是這樣的應(yīng)對(duì)策略會(huì)讓我們的程序出現(xiàn)越來越多的 null 判定。一個(gè)良好的程序設(shè)計(jì)應(yīng)該讓代碼中盡量少出現(xiàn) null 關(guān)鍵字,而 8th 所提供的 Optional 類則在減少 NullPointException 的同時(shí),也提升了代碼的美觀度。但首先我們需要明確的是它并 不是對(duì) null 關(guān)鍵字的替代策略,而是對(duì)于 null 判定提供了一種更加優(yōu)雅的實(shí)現(xiàn),從而盡可能地避免 NullPointException

下面通過一個(gè)小示例直觀感受一下,假設(shè)我們需要返回一個(gè)字符串的長度,如果不借助第三方工具類,我們需要調(diào)用 str.length() 方法:

if(null == str) { // 空指針判定
    return 0;
}
return str.length();

如果采用 Optional 類,實(shí)現(xiàn)如下:

return Optional.ofNullable(str).map(String::length).orElse(0);

Optional 的代碼相對(duì)更加簡潔,當(dāng)代碼量較大時(shí),我們很容易忘記進(jìn)行 null 判定,但是使用 Optional 類則會(huì)避免這類問題。

一. 基本使用 1.1 Optional 對(duì)象的創(chuàng)建

創(chuàng)建空對(duì)象

Optional optStr = Optional.empty();

上面的示例代碼調(diào)用 empty() 方法創(chuàng)建了一個(gè)空的 Optional 對(duì)象型。

創(chuàng)建對(duì)象:不允許我空

Optional 提供了方法 of() 用于創(chuàng)建非空對(duì)象,該方法要求傳入的參數(shù)不能為空,否則拋 NullPointException,示例如下:

Optional optStr = Optional.of(str);  // 當(dāng)str為null的時(shí)候,將拋出NullPointException

創(chuàng)建對(duì)象:允許為空

如果不能確定傳入的參數(shù)是否存在 null 值的可能性,則可以用 Optional 的 ofNullable() 方法創(chuàng)建對(duì)象,如果入?yún)?null 則創(chuàng)建一個(gè)空對(duì)象。示例如下:

Optional optStr = Optional.ofNullable(str);  // 如果str是null,則創(chuàng)建一個(gè)空對(duì)象
1.2 流式數(shù)據(jù)處理

流式數(shù)據(jù)處理也是 8th 給我們帶來的一個(gè)重量級(jí)新特性,讓我們對(duì)集合的操作變得更加簡潔和高效,本系列下一篇將對(duì)流式數(shù)據(jù)處理進(jìn)行全面的講解。Optional 類也提供了兩個(gè)基本的流失處理:映射和過濾。

為了演示,我們?cè)O(shè)計(jì)了一個(gè) User 類,如下:

public class User {
    private long id;
    private String name;
    private int age;
    private Optional phone;
    private Optional email;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 省略setter和getter
}

手機(jī)和郵箱不是一個(gè)人的必須有的,所以我們利用 Optional 類定義。

映射:map 與 flatMap

映射是將輸入轉(zhuǎn)換成另外一種形式的輸出的操作,比如前面例子中我們輸入字符串,而輸出的是字符串的長度,這就是一種映射,我們利用方法 map() 進(jìn)行實(shí)現(xiàn)。假設(shè)我們希望獲得一個(gè)人的姓名,我們可以如下實(shí)現(xiàn):

String name = Optional.ofNullable(user).map(User::getName).orElse("no name");

這樣當(dāng)入?yún)?user 不為空的時(shí)候則返回其 name,否則返回 no name。如我我們希望通過上面方式得到 phone 或 email,利用上面的方式則行不通了,因?yàn)?map 之后返回的是 Optional,我們把這種稱為 Optional 嵌套,我們必須再 map 一次才能拿到我們想要的結(jié)果:

long phone = optUser.map(User::getPhone).map(Optional::get).orElse(-1L);

其實(shí)這個(gè)時(shí)候更好的方式是利用 flatMap,一步拿到我們想要的結(jié)果:

long phone = optUser.flatMap(User::getPhone).orElse(-1L);

flapMap 可以將方法返回的各個(gè)流扁平化成為一個(gè)流,具體在下一篇專門講流式數(shù)據(jù)處理的文章中細(xì)說。

過濾:fliter

filiter,顧名思義是過濾的操作,我們可以將過濾操作做為參數(shù)傳遞給該方法以實(shí)現(xiàn)過濾目的,假如我們希望篩選 18 周歲以上的成年人,則可以實(shí)現(xiàn)如下:

optUser.filter(u -> u.getAge() >= 18).ifPresent(u -> System.out.println("Adult:" + u));
1.3 默認(rèn)行為

默認(rèn)行為是當(dāng) Optional 在不滿足條件時(shí)所執(zhí)行的操作,比如在上面的例子中我們使用的 orElse() 就是一個(gè)默認(rèn)操作,用于在 Optional 對(duì)象為空時(shí)執(zhí)行特定操作,當(dāng)然也有一些默認(rèn)操作是當(dāng)滿足條件的對(duì)象存在時(shí)執(zhí)行的操作。

get()

get 方法用于獲取變量的值,但是當(dāng)變量不存在時(shí)則會(huì)拋出 NoSuchElementException,所以如果不確定變量是否存在則不建議使用

orElse(T other)

當(dāng) Optional 的變量不滿足給定條件時(shí),則執(zhí)行 orElse,比如前面當(dāng) str 為 null 時(shí)返回 0。

orElseGet(Supplier expectionSupplier)

如果條件不成立時(shí)需要執(zhí)行相對(duì)復(fù)雜的邏輯而不是簡單的返回操作,則可以使用 orElseGet 實(shí)現(xiàn):

long phone = optUser.map(User::getPhone).map(Optional::get).orElseGet(() -> {
    // do something here
    return -1L;
});

orElseThrow(Supplier expectionSupplier)

get() 方法類似,都是在不滿足條件時(shí)返回異常,不過這里我們可以指定返回的異常類型。

ifPresent(Consumer)

當(dāng)滿足條件時(shí)執(zhí)行傳入的參數(shù)化操作。

二. 注意事項(xiàng)

Optional 是一個(gè) final 類且未實(shí)現(xiàn)任何接口,所以當(dāng)我們?cè)诶迷擃惏b定義類的屬性的時(shí)候,如果我們定義的類有序列化的需求,那么因?yàn)?Optional 沒有實(shí)現(xiàn) Serializable 接口,這個(gè)時(shí)候執(zhí)行序列化操作就會(huì)有問題:

public class User implements Serializable {
    private long id;
    private String name;
    private int age;
    private Optional phone;  // 不能序列化
    private Optional email;  // 不能序列化
}

不過我們可以采用如下替換策略 Optinal:

private long phone;

public Optional getPhone() {
    return Optional.ofNullable(this.phone);
}

看來 Optional 類在設(shè)計(jì)的時(shí)候就沒有考慮將它作為類的字段使用。

最后提醒一點(diǎn),Optional 好用但不能濫用,在設(shè)計(jì)一個(gè)接口方法時(shí)是否采取 Optional 類型返回需要斟酌,一味的使用會(huì)讓代碼變得比較啰嗦,反而破壞了代碼的簡潔性。

鑒于作者水平有限,文中不免有錯(cuò)誤之處,歡迎批評(píng)指正
個(gè)人博客:www.zhenchao.org

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

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

相關(guān)文章

  • Java 8th 函數(shù)編程:lambda 表達(dá)

    摘要:自定義函數(shù)式接口我們?cè)谇懊胬又袑?shí)現(xiàn)的蘋果篩選接口就是一個(gè)函數(shù)式接口定義如下,正因?yàn)槿绱宋覀兛梢詫⒑Y選邏輯參數(shù)化,并應(yīng)用表達(dá)式僅包含一個(gè)抽象方法,依照定義可以將其視為一個(gè)函數(shù)式接口。 Lambda 表達(dá)式是 java 8th 給我們帶來的幾個(gè)重量級(jí)新特性之一,借用 lambda 表達(dá)式可以讓我們的程序設(shè)計(jì)更加簡潔。最近新的項(xiàng)目摒棄了 6th 版本,全面基于 8th 進(jìn)行開發(fā),本文將探討...

    luffyZh 評(píng)論0 收藏0
  • Java8新特性總覽

    摘要:新特性總覽標(biāo)簽本文主要介紹的新特性,包括表達(dá)式方法引用流默認(rèn)方法組合式異步編程新的時(shí)間,等等各個(gè)方面。還有對(duì)應(yīng)的和類型的函數(shù)連接字符串廣義的歸約匯總起始值,映射方法,二元結(jié)合二元結(jié)合。使用并行流時(shí)要注意避免共享可變狀態(tài)。 Java8新特性總覽 標(biāo)簽: java [TOC] 本文主要介紹 Java 8 的新特性,包括 Lambda 表達(dá)式、方法引用、流(Stream API)、默認(rèn)方...

    mayaohua 評(píng)論0 收藏0
  • Java8學(xué)習(xí)小記

    摘要:但有一個(gè)限制它們不能修改定義的方法的局部變量的內(nèi)容。如前所述,這種限制存在的原因在于局部變量保存在棧上,并且隱式表示它們僅限于其所在線程。 2014年,Oracle發(fā)布了Java8新版本。對(duì)于Java來說,這顯然是一個(gè)具有里程碑意義的版本。尤其是那函數(shù)式編程的功能,避開了Java那煩瑣的語法所帶來的麻煩。 這可以算是一篇Java8的學(xué)習(xí)筆記。將Java8一些常見的一些特性作了一個(gè)概要的...

    CHENGKANG 評(píng)論0 收藏0
  • Java8實(shí)用技能

    大概一年多之前,我對(duì)java8的理解還僅限一些只言片語的文章之上,后來出于對(duì)函數(shù)式編程的興趣,買了本參考書看了一遍,然后放在了書架上,后來,當(dāng)我接手大客戶應(yīng)用的開發(fā)工作之后,java8的一些工具,對(duì)我的效率有了不小的提升,因此想記錄一下java8的一些常用場(chǎng)景,我希望這會(huì)成為一個(gè)小字典,能讓我免于頻繁翻書,但是總能找到自己想找的知識(shí)。 用于舉例的model: @Data public class ...

    microcosm1994 評(píng)論0 收藏0
  • Introducing FP in Java8

    摘要:函數(shù)副作用會(huì)給程序設(shè)計(jì)帶來不必要的麻煩,引入潛在的,并降低程序的可讀性。所以只能采用這種曲線救國的方式。則是把這種曲線救國拿到了臺(tái)面上,并昭告天下,同時(shí)還對(duì)提供了一些語法支持。是自由變量,提供執(zhí)行上下文,觸發(fā)閉包執(zhí)行。 背景 自從2013年放棄了Java就再也沒有碰過。期間Java還發(fā)布了重大更新:引入lambda,但是那會(huì)兒我已經(jīng)玩了一段時(shí)間Scala,對(duì)Java已經(jīng)瞧不上眼。相比S...

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

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

0條評(píng)論

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