欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java8中Optional操作的實(shí)際應(yīng)用

 更新時間:2022年02月16日 11:49:13   作者:湯圓學(xué)Java  
Optional類是一個可以為null的容器對象,如果值存在則isPresent()方法會返回true,調(diào)用get()方法會返回該對象,下面這篇文章主要給大家介紹了關(guān)于Java8中Optional操作實(shí)際應(yīng)用的相關(guān)資料,需要的朋友可以參考下

簡介

目的:Optional的出現(xiàn)主要是為了解決null指針問題,也叫NPE(NullPointerException)

外形:Optional外形酷似容器(其實(shí)它就是一個容器),只是這個容器比較特殊,因?yàn)樗荒?strong>存放一個對象,運(yùn)氣不好的話這個對象還是個null

操作:Optional從操作上來看,又跟前面的Stream流式操作很像,比如過濾filter - 提取map等

下面我們用比較簡單的例子來對比著看下,Optional的一些基礎(chǔ)用法

正文

1. Optional是什么

Optional是一個容器,只能存放一個對象(可為null)

Optional的出現(xiàn)是

  • 一個是為了解決NPE問題(阿里開發(fā)手冊也有提到這一點(diǎn),點(diǎn)擊可直接下載,官方鏈接)
  • 另一個是為了代碼更加清晰可讀,因?yàn)镺ptional這個名字的靈感就是來自英文optional(可選的),意思就是說這個對象可以為空,可以不為空

2. 沒它 VS 有它

下面我們用舊代碼和新代碼來對比著看(所謂的新舊是以Java8為分割線)

案例1:現(xiàn)有C類,我們要提取C.name屬性

public class OptionalDemo {
    private static final String DEFAULT_NAME = "javalover";

    public static void main(String[] args) {
      // 傳入null,以身試法  
      getName(null);
    }
    // 取出c.name
    public static void getName(C c){
        // 舊代碼 Java8之前
        String name = (c!=null ? c.getName() : DEFAULT_NAME);
        System.out.println("old: "+name);
        // 新代碼 Java8之后(下面的三個操作方法后面會介紹,這里簡單了解下)
        String nameNew = Optional
            				// 工廠方法,創(chuàng)建Optional<C>對象,如果c為null,則創(chuàng)建空的Optional<C>對象
                            .ofNullable(c)
            				// 提取name,這里要注意,即使c==null,這里也不會拋出NPE,而是返回空的Optional<String>,所以在處理數(shù)據(jù)時,我們不需要擔(dān)心空指針異常
                            .map(c1->c1.getName())
            				// 獲取optional的屬性值,如果為null,則返回給定的實(shí)參DEFAULT_NAME
                            .orElse(DEFAULT_NAME);

        System.out.println("new: "+nameNew);
    }
}
class C{
    private String name;

    public C(String name) {
        this.name = name;
    }
  // 省略getter/setter
}

乍一看,好像Java8之前的舊代碼更合適啊,只需要一個三目運(yùn)算符

再看Optional操作,發(fā)現(xiàn)并沒有那么簡潔

是這樣的,如果只是一層判斷,那普通的if判斷做起來更方便;

但是如果嵌套兩層呢,比如b.getC().getName()?

下面我們就看下,兩層嵌套會怎么樣

例子2:現(xiàn)多了一個B類(依賴C類),我們要從對象B中提取C的屬性name,即b.getC().getName()

public static void getName2(B b){
        // 舊代碼
        String name = (b!=null ? ( b.getC()!=null ? b.getC().getName() : DEFAULT_NAME) : DEFAULT_NAME);
        // 新代碼
        String nameNew = Optional
                .ofNullable(b)
                .map(b1->b1.getC())
                .map(c1->c1.getName())
                .orElse(DEFAULT_NAME);
        System.out.println(nameNew);
    }

class B{
    private C c;

    public B(C c) {
        this.c = c;
    }
  // 省略getter/setter
}

這次不管是乍一看,還是一直看,都是Optional更勝一籌

例子3:現(xiàn)多了一個A類(依賴B類),我們要提取a.getB().getC().getName()

等等等,省略號

意思到就行,反正要說的就是單從判空來看的話,Optional肯定是好過三目運(yùn)算符的(if/else這里就不舉了,它的嵌套只會更多)

3. 核心操作

因?yàn)镺ptional主要是操作數(shù)據(jù)(類似數(shù)據(jù)庫操作),所以我們這里從數(shù)據(jù)的角度來進(jìn)行分析

這里我們可以分為三種操作:保存數(shù)據(jù)、處理數(shù)據(jù)、獲取數(shù)據(jù)

保存數(shù)據(jù)

  • (沒有默認(rèn)值)public static <T> Optional<T> of(T value) :填充 T value 到 Optional 的屬性中;如果 value==null,則拋出NPE
  • (默認(rèn)null)public static <T> Optional<T> ofNullable(T value) :填充 T value 到 Optional 的屬性中;如果引用為null,則填充null
  • (構(gòu)造一個空的Optional)public static<T> Optional<T> empty():單純地創(chuàng)建一個數(shù)據(jù)為null的空Optional,即直接填充null到 Optional 的屬性中【不常用】

處理數(shù)據(jù)

  • (提取)public<U> Optional<U> map(Function<? super T, ? extends U> mapper) :提取Optional中屬性T的某個屬性值U,并將U填充到新的Optional中并返回
  • (過濾)public Optional<T> filter(Predicate<? super T> predicate) :過濾Optional中屬性T的某個屬性值,符合條件則將T填充到新的Optional中并返回
  • (扁平化提?。?code>public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper):提取Optional中屬性T的某個屬性Optional<U>,直接返回

獲取數(shù)據(jù)

  • public T orElse(T other) :獲取數(shù)據(jù),如果數(shù)據(jù)為null,則返回T other
  • public T orElseGet(Supplier<? extends T> other):獲取數(shù)據(jù),如果數(shù)據(jù)為null,則通過函數(shù)式接口other返回一個新的數(shù)據(jù)T
  • public T get() :獲取數(shù)據(jù),如果數(shù)據(jù)為null,則報NPE【不常用】

上面這些操作中,不常用的就是get()和empty()

其他的就不舉了,這里主要說下map()和flatMap()

如下圖所示:

map()主要是提取Optional中的屬性C的屬性name,然后再包裝到新的Optional

輸入Optional<C>, 輸出Optional<String>(即Optional<c.name>)

String nameNew = Optional
                    .ofNullable(c)
                    .map(c1->c1.getName())
                    .orElse("xxx");

flatMap()主要是提取Optional中的屬性B的Optional<C>屬性中的C的值,然后再包裝到新的Optional

輸入Optional<B>,輸出Optional<C>

public class FlatMapDemo {
    private static final String DEFAULT_NAME = "javalover";

    public static void main(String[] args) {
        getName(null);
    }

    // 取出 b.c.name
    public static void getName(B b){
        C c = Optional
                .ofNullable(b)
            	// 這里扁平化處理,提取Optional<C>中的C
            	// 如果用map,則返回的是Optional<Optional<C>>
                .flatMap(b->b.getC())
                .orElse(new C("xxx"));
        System.out.println(c.getName());
    }
}

class B{
    private Optional<C> c;

    public Optional<C> getC() {
        return c;
    }

    public void setC(C c) {
        this.c = Optional.ofNullable(c);
    }
}

class C{
    private String name;

    public C(String name) {
        this.name = name;
    }
    // 省略getter/setter
}

4. 應(yīng)用

從規(guī)范角度來講,是為了代碼清晰,一看用Optional<T>變量,就知道T可能為null;

從編碼角度來講,主要是應(yīng)用在非空判斷;但是實(shí)際場景的話,有兩個

  • 沒有用Optional進(jìn)行包裹的參數(shù):比如上面講到的例子,傳來的參數(shù)就是普通對象,我們就需要自己用Optional容器來包裹傳來的參數(shù),然后進(jìn)行后續(xù)操作
// 取出c.name
public static void getName(C c){
    // 自己手動包裝 Optional<C>
    String nameNew = Optional
        .ofNullable(c)
        .map(c1->c1.getName())
        .orElse(DEFAULT_NAME);

    System.out.println("new: "+nameNew);
}
  • 有用Optional進(jìn)行包裹的參數(shù):比如數(shù)據(jù)庫查詢時,我們可以用Optional來包裹查詢的結(jié)果并返回,這樣我們分析結(jié)果的時候,只需要通過orElse()來獲取,同時還可以設(shè)定默認(rèn)值
// 返回Optional<Car>,通過.orElse(defaultCar)就可以獲取返回值,如果返回值為null,還可以設(shè)定一個默認(rèn)值defaultCar
Optional<Car> selectOne(SelectStatementProvider selectStatement);

總結(jié)

  • Optional是什么:一個容器,存放一個對象,對象可以為null

  • 沒它 VS 有它:看場景

    • 如果只是單個的if/else判斷,那就沒它會好點(diǎn);

    • 如果嵌套比較多,或者本來傳來的數(shù)據(jù)就是Optional類型,那肯定是Optional合適

  • 核心操作:不常用的這里就不寫了

    • 保存數(shù)據(jù):工廠方法 of()ofNullable()
    • 處理數(shù)據(jù):map(), filter(), flatMap()
    • 獲取數(shù)據(jù):orElse()
  • 應(yīng)用:主要用在非空判斷,實(shí)際場景的話,我們可以用在數(shù)據(jù)庫查詢語句中

總結(jié)

到此這篇關(guān)于Java8中Optional操作的文章就介紹到這了,更多相關(guān)Java8中Optional操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • RocketMQ順序消息的原理與特點(diǎn)

    RocketMQ順序消息的原理與特點(diǎn)

    RocketMQ作為一款純java、分布式、隊(duì)列模型的開源消息中間件,支持事務(wù)消息、順序消息、批量消息、定時消息、消息回溯等,本篇我們了解如何實(shí)現(xiàn)順序消息的原理與特點(diǎn)
    2023-02-02
  • Spring Boot 項(xiàng)目搭建教程及注解

    Spring Boot 項(xiàng)目搭建教程及注解

    下面小編就為大家?guī)硪黄猄pring Boot 項(xiàng)目搭建教程及注解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 一文詳解如何在控制臺顯示MyBatis的SQL語句

    一文詳解如何在控制臺顯示MyBatis的SQL語句

    這篇文章主要為大家介紹了如何在控制臺顯示MyBatis的SQL語句實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Java中字符串的一些常見方法分享

    Java中字符串的一些常見方法分享

    這篇文章主要介紹了Java中字符串的一些常見方法,需要的朋友可以參考下
    2014-02-02
  • springboot中如何通過main方法調(diào)用service或dao

    springboot中如何通過main方法調(diào)用service或dao

    這篇文章主要介紹了springboot中如何通過main方法調(diào)用service或dao,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java中BigDecimal的舍入模式解析(RoundingMode)

    Java中BigDecimal的舍入模式解析(RoundingMode)

    這篇文章主要介紹了Java中BigDecimal的舍入模式解析(RoundingMode),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java編程讀寫鎖詳解

    Java編程讀寫鎖詳解

    本篇文章給大家詳細(xì)分享了Java編程讀寫鎖的相關(guān)原理以及知識點(diǎn)內(nèi)容,有興趣的朋友們可以參考下。
    2018-08-08
  • springmvc處理模型數(shù)據(jù)Map過程解析

    springmvc處理模型數(shù)據(jù)Map過程解析

    這篇文章主要介紹了springmvc處理模型數(shù)據(jù)Map過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • Java中ArrayList的工作原理詳解

    Java中ArrayList的工作原理詳解

    本文主要介紹了Java中ArrayList的工作原理,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • java?Date獲取本月的開始時間與結(jié)束時間

    java?Date獲取本月的開始時間與結(jié)束時間

    這篇文章主要為大家介紹了java?Date獲取本月的開始時間與結(jié)束時間示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2023-05-05

最新評論