国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java8(5):使用 Optional 處理 null

liuchengxu / 2019人閱讀

摘要:與方法的區(qū)別在于,方法傳入的參數(shù)為一個(gè)接口的實(shí)現(xiàn)當(dāng)中有值的時(shí)候,返回值當(dāng)中沒有值的時(shí)候,返回從該獲得的值。為的用戶沒有找到舉一個(gè)的用途在的控制器中,我們可以配置統(tǒng)一處理各種異常。

寫過 Java 程序的同學(xué),一般都遇到過 NullPointerException :) —— 為了不拋出這個(gè)異常,我們便會(huì)寫如下的代碼:

User user = getUserById(id);
if (user != null) {
    String username = user.getUsername();
    System.out.println("Username is: " + username); // 使用 username
}

但是很多時(shí)候,我們可能會(huì)忘記寫 if (user != null) —— 如果在開發(fā)階段就發(fā)現(xiàn)那還好,但是如果在開發(fā)階段沒有測(cè)試到問題,等到上線卻出了 NullPointerException ... 畫面太美,我不敢繼續(xù)想下去。

為了解決這種尷尬的處境,JDK 終于在 Java8 的時(shí)候加入了 Optional 類,查看 Optional 的 javadoc 介紹:

A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.

這是一個(gè)可以包含或者不包含非 null 值的容器。如果值存在則 isPresent()方法會(huì)返回 true,調(diào)用 get() 方法會(huì)返回該對(duì)象。

JDK 提供三個(gè)靜態(tài)方法來構(gòu)造一個(gè) Optional
1.Optional.of(T value),該方法通過一個(gè)非 nullvalue 來構(gòu)造一個(gè) Optional,返回的 Optional 包含了 value 這個(gè)值。對(duì)于該方法,傳入的參數(shù)一定不能為 null,否則便會(huì)拋出 NullPointerException

2.Optional.ofNullable(T value),該方法和 of 方法的區(qū)別在于,傳入的參數(shù)可以為 null —— 但是前面 javadoc 不是說 Optional 只能包含非 null 值嗎?我們可以看看 ofNullable 方法的源碼:

原來該方法會(huì)判斷傳入的參數(shù)是否為 null,如果為 null 的話,返回的就是 Optional.empty()

3.Optional.empty(),該方法用來構(gòu)造一個(gè)空的 Optional,即該 Optional 中不包含值 —— 其實(shí)底層實(shí)現(xiàn)還是 如果 Optional 中的 valuenull 則該 Optional 為不包含值的狀態(tài),然后在 API 層面將 Optional 表現(xiàn)的不能包含 null 值,使得 Optional 只存在 包含值不包含值 兩種狀態(tài)。

前面 javadoc 也有提到,OptionalisPresent() 方法用來判斷是否包含值,get() 用來獲取 Optional 包含的值 —— 值得注意的是,如果值不存在,即在一個(gè)Optional.empty 上調(diào)用 get() 方法的話,將會(huì)拋出 NoSuchElementException 異常
我們假設(shè) getUserById 已經(jīng)是個(gè)客觀存在的不能改變的方法,那么利用 isPresentget 兩個(gè)方法,我們現(xiàn)在能寫出下面的代碼:

Optional user = Optional.ofNullable(getUserById(id));
if (user.isPresent()) {
    String username = user.get().getUsername();
    System.out.println("Username is: " + username); // 使用 username
}

好像看著代碼是優(yōu)美了點(diǎn) —— 但是事實(shí)上這與之前判斷 null 值的代碼沒有本質(zhì)的區(qū)別,反而用 Optional 去封裝 value,增加了代碼量。所以我們來看看 Optional 還提供了哪些方法,讓我們更好的(以正確的姿勢(shì))使用 Optional

1.ifPresent

如果 Optional 中有值,則對(duì)該值調(diào)用 consumer.accept,否則什么也不做。
所以對(duì)于上面的例子,我們可以修改為:

Optional user = Optional.ofNullable(getUserById(id));
user.ifPresent(u -> System.out.println("Username is: " + u.getUsername()));

2.orElse

如果 Optional 中有值則將其返回,否則返回 orElse 方法傳入的參數(shù)。

User user = Optional
        .ofNullable(getUserById(id))
        .orElse(new User(0, "Unknown"));
        
System.out.println("Username is: " + user.getUsername());

3.orElseGet

orElseGetorElse 方法的區(qū)別在于,orElseGet 方法傳入的參數(shù)為一個(gè) Supplier 接口的實(shí)現(xiàn) —— 當(dāng) Optional 中有值的時(shí)候,返回值;當(dāng) Optional 中沒有值的時(shí)候,返回從該 Supplier 獲得的值。

User user = Optional
        .ofNullable(getUserById(id))
        .orElseGet(() -> new User(0, "Unknown"));
        
System.out.println("Username is: " + user.getUsername());

4.orElseThrow

orElseThroworElse 方法的區(qū)別在于,orElseThrow 方法當(dāng) Optional 中有值的時(shí)候,返回值;沒有值的時(shí)候會(huì)拋出異常,拋出的異常由傳入的 exceptionSupplier 提供。

User user = Optional
        .ofNullable(getUserById(id))
        .orElseThrow(() -> new EntityNotFoundException("id 為 " + id + " 的用戶沒有找到"));

舉一個(gè) orElseThrow 的用途:在 SpringMVC 的控制器中,我們可以配置統(tǒng)一處理各種異常。查詢某個(gè)實(shí)體時(shí),如果數(shù)據(jù)庫(kù)中有對(duì)應(yīng)的記錄便返回該記錄,否則就可以拋出 EntityNotFoundException ,處理 EntityNotFoundException 的方法中我們就給客戶端返回Http 狀態(tài)碼 404 和異常對(duì)應(yīng)的信息 —— orElseThrow 完美的適用于這種場(chǎng)景。

@RequestMapping("/{id}")
public User getUser(@PathVariable Integer id) {
    Optional user = userService.getUserById(id);
    return user.orElseThrow(() -> new EntityNotFoundException("id 為 " + id + " 的用戶不存在"));
}

@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity handleException(EntityNotFoundException ex) {
    return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
}

5.map

如果當(dāng)前 OptionalOptional.empty,則依舊返回 Optional.empty;否則返回一個(gè)新的 Optional,該 Optional 包含的是:函數(shù) mapper 在以 value 作為輸入時(shí)的輸出值。

String username = Optional.ofNullable(getUserById(id))
                        .map(user -> user.getUsername())
                        .orElse("Unknown")
                        .ifPresent(name -> System.out.println("Username is: " + name));

而且我們可以多次使用 map 操作:

Optional username = Optional.ofNullable(getUserById(id))
                                .map(user -> user.getUsername())
                                .map(name -> name.toLowerCase())
                                .map(name -> name.replace("_", " "))
                                .orElse("Unknown")
                                .ifPresent(name -> System.out.println("Username is: " + name));

6.flatMap

flatMap 方法與 map 方法的區(qū)別在于,map 方法參數(shù)中的函數(shù) mapper 輸出的是值,然后 map 方法會(huì)使用 Optional.ofNullable 將其包裝為 Optional;而 flatMap 要求參數(shù)中的函數(shù) mapper 輸出的就是 Optional

Optional username = Optional.ofNullable(getUserById(id))
                                .flatMap(user -> Optional.of(user.getUsername()))
                                .flatMap(name -> Optional.of(name.toLowerCase()))
                                .orElse("Unknown")
                                .ifPresent(name -> System.out.println("Username is: " + name));

7.filter

filter 方法接受一個(gè) Predicate 來對(duì) Optional 中包含的值進(jìn)行過濾,如果包含的值滿足條件,那么還是返回這個(gè) Optional;否則返回 Optional.empty

Optional username = Optional.ofNullable(getUserById(id))
                                .filter(user -> user.getId() < 10)
                                .map(user -> user.getUsername());
                                .orElse("Unknown")
                                .ifPresent(name -> System.out.println("Username is: " + name));

有了 Optional,我們便可以方便且優(yōu)雅的在自己的代碼中處理 null 值,而不再需要一昧通過容易忘記和麻煩的 if (object != null) 來判斷值不為 null。如果你的程序還在使用 Java8 之前的 JDK,可以考慮引入 Google 的 Guava 庫(kù) —— 事實(shí)上,早在 Java6 的年代,Guava 就提供了 Optional 的實(shí)現(xiàn)。

號(hào)外:Java9 對(duì) Optional 的增強(qiáng)
即將在今年 7 月到來的 JDK9 中,在 Optional 類中添加了三個(gè)新的方法:

public Optional or(Supplier> supplier)

or 方法的作用是,如果一個(gè) Optional 包含值,則返回自己;否則返回由參數(shù) supplier 獲得的 Optional

public void ifPresentOrElse(Consumer action, Runnable emptyAction)

ifPresentOrElse 方法的用途是,如果一個(gè) Optional 包含值,則對(duì)其包含的值調(diào)用函數(shù) action,即 action.accept(value),這與 ifPresent 一致;與 ifPresent 方法的區(qū)別在于,ifPresentOrElse 還有第二個(gè)參數(shù) emptyAction —— 如果 Optional 不包含值,那么 ifPresentOrElse 便會(huì)調(diào)用 emptyAction,即 emptyAction.run()

public Stream stream()

stream 方法的作用就是將 Optional 轉(zhuǎn)為一個(gè) Stream,如果該 Optional 中包含值,那么就返回包含這個(gè)值的 Stream;否則返回一個(gè)空的 StreamStream.empty())。

舉個(gè)例子,在 Java8,我們會(huì)寫下面的代碼:

// 此處 getUserById 返回的是 Optional
public List getUsers(Collection userIds) {
       return userIds.stream()
                .map(this::getUserById)      // 獲得 Stream>
                .filter(Optional::isPresent) // 去掉不包含值的 Optional,否則如果存在為空的 Optional 下面的 get 會(huì)拋出異常
                .map(Optional::get)          // 變?yōu)?Stream
                .collect(Collectors.toList());
}

而有了 Optional.stream(),我們就可以將其簡(jiǎn)化為:

public List getUsers(Collection userIds) {
    return userIds.stream()
                .map(this::getUserById)    // 獲得 Stream>
                .flatMap(Optional::stream) // Stream 的 flatMap 方法將多個(gè)流合成一個(gè)流,如果 Optional 為空則對(duì)應(yīng)是空的 Stream,合并時(shí)會(huì)跳過
                .collect(Collectors.toList());
}

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/66812.html

相關(guān)文章

  • 樂字節(jié)Java8核心特性之Optional

    摘要:大家好啊,上次小樂給大家介紹了最最重要的一個(gè)特性流,點(diǎn)擊可以回顧哦。并且可以避免空指針異常。這種操作對(duì)于參數(shù)判斷提供很大便利,例如參數(shù)滿足指定條件的后續(xù)操作查詢操作字符串拼接,常見的處理多請(qǐng)求頁面轉(zhuǎn)發(fā)處理等操作。 大家好啊,上次小樂給大家介紹了Java8最最重要的一個(gè)特性——Stream流,點(diǎn)擊可以回顧哦。 Optional類(java.util.Optional)是一個(gè)容器類,代表一...

    姘存按 評(píng)論0 收藏0
  • Java8新特性之Optional

    摘要:上一篇小樂帶大家了解了新特性之,接下來將會(huì)繼續(xù)述說新特性之類是一個(gè)容器類,代表一個(gè)值存在或不存在,原來用表示一個(gè)值不存在,現(xiàn)在可以更好的表達(dá)這個(gè)概念。并且可以避免空指針異常。如果有值則將其返回,否則拋出。隱士地其中進(jìn)行了判斷。 上一篇小樂帶大家了解了Java8新特性之Stream,接下來將會(huì)繼續(xù)述說Java新特性之Optional showImg(https://segmentfaul...

    stackfing 評(píng)論0 收藏0
  • 【修煉內(nèi)功】[Java8] 使用Optional的正確姿勢(shì)及序列化問題

    摘要:本文已收錄修煉內(nèi)功躍遷之路的為解決空的問題帶來了很多新思路,查看源碼,實(shí)現(xiàn)非常簡(jiǎn)單,邏輯也并不復(fù)雜。 本文已收錄【修煉內(nèi)功】躍遷之路 showImg(https://segmentfault.com/img/bVbrCvp?w=852&h=480); Java8的Optional為解決空的問題帶來了很多新思路,查看Optional源碼,實(shí)現(xiàn)非常簡(jiǎn)單,邏輯也并不復(fù)雜。Stuart Ma...

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

    摘要:函數(shù)副作用會(huì)給程序設(shè)計(jì)帶來不必要的麻煩,引入潛在的,并降低程序的可讀性。所以只能采用這種曲線救國(guó)的方式。則是把這種曲線救國(guó)拿到了臺(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
  • Java8-7-Optional類詳解

    摘要:上一篇我們?cè)敿?xì)介紹了函數(shù)式接口中主要的一些方法使用,本篇介紹的雖然并不是一個(gè)函數(shù)式接口,但是也是一個(gè)極其重要的類。并不是我們之前介紹的一系列函數(shù)式接口,它是一個(gè),主要作用就是解決中的。 上一篇我們?cè)敿?xì)介紹了Predicate函數(shù)式接口中主要的一些方法使用,本篇介紹的Optional雖然并不是一個(gè)函數(shù)式接口,但是也是一個(gè)極其重要的類。 Optional并不是我們之前介紹的一系列函數(shù)式接口...

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

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

0條評(píng)論

閱讀需要支付1元查看
<