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

JDK8新出Optional類的方法探索與思考分析

 更新時(shí)間:2023年08月23日 14:18:54   作者:彼岸花開可奈何  
這篇文章主要為大家介紹了JDK8新出Optional類的發(fā)方法示例探索與思考分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

所有的 Java 程序員基本都會(huì)遇到 NullPointerException 異常,一般處理這個(gè)問題可能不會(huì)是很難,但是有時(shí)去排查到底是哪引起的會(huì)耗費(fèi)很長時(shí)間很是麻煩。最近了解到 JDK1.8 新增加了一個(gè) Optional 類可以避免一些 NullPointerException 異常,下面讓我們一起去了解一下它吧。

基于值的類(Value-based Classes)

有些類,如 java.util.Optional 和 java.time.LocalDateTime,是基于值的。基于值的類的實(shí)例:

  • 是最終的和不可變的(盡管可能包含對(duì)可變對(duì)象的引用);
  • 具有 equals、hashCode 和 toString 的實(shí)現(xiàn),這些實(shí)現(xiàn)僅根據(jù)實(shí)例的狀態(tài)計(jì)算,而不是根據(jù)實(shí)例的標(biāo)識(shí)或任何其他對(duì)象或變量的狀態(tài)計(jì)算;
  • 不使用對(duì)身份敏感的操作,例如實(shí)例之間的引用相等(==)、實(shí)例的身份哈希代碼或?qū)?shí)例的內(nèi)部鎖進(jìn)行同步;
  • 僅基于 equals() 而不是基于引用相等 (==) 被視為相等;
  • 沒有可訪問的構(gòu)造函數(shù),而是通過工廠方法進(jìn)行實(shí)例化,這些方法不提交返回實(shí)例的標(biāo)識(shí);
  • 當(dāng)相等時(shí)是可自由替換的,這意味著在任何計(jì)算或方法調(diào)用中,根據(jù) equals() 交換任何兩個(gè)相等的實(shí)例 x 和 y 都不會(huì)產(chǎn)生明顯的行為變化。

如果程序試圖區(qū)分對(duì)基于值的類的相等值的兩個(gè)引用,無論是直接通過引用相等,還是間接通過調(diào)用同步、身份哈希、序列化或任何其他身份敏感機(jī)制,都可能產(chǎn)生不可預(yù)測的結(jié)果。在基于值的類的實(shí)例上使用這種對(duì)身份敏感的操作可能會(huì)產(chǎn)生不可預(yù)測的影響,應(yīng)該避免。

簡單地說,基于值的類的實(shí)例是最終的,不可變的,并且這些實(shí)例沒有適當(dāng)?shù)臓顟B(tài)和標(biāo)識(shí),因此某些操作是特定于標(biāo)識(shí)的,因此不應(yīng)使用。

一、Optional中的基本方法

Optional 類位于 java.util 包下,它是一個(gè)容器對(duì)象,可能包含也可能不包含非空值。

這是一個(gè)基于值的類;在Optional實(shí)例上使用身份敏感操作(包括引用相等(==)、身份哈希碼或同步)可能會(huì)產(chǎn)生不可預(yù)測的結(jié)果,應(yīng)該避免。

1、創(chuàng)建方法

empty()

返回一個(gè)空的 Optional 實(shí)例

public class Main {
    public static void main(String[] args) {
        System.out.println(Optional);
    }
}
// 輸出
Optional.empty

注意:不要通過與Option.empty()返回的實(shí)例進(jìn)行==比較來避免測試對(duì)象是否為空,因?yàn)椴荒鼙WC它是單例的。

of(T value)

返回一個(gè)帶值的 Optional,如果 value 是 null 會(huì)拋出 NullPointerException 異常

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.of("emanjusaka");
        System.out.println(emanjusaka);
    }
// 輸出
Optional[emanjusaka]

ofNullable(T value)

如果非空,返回描述指定值的 Optional,否則返回空 Optional。

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.ofNullable("emanjusaka");
        System.out.println(emanjusaka);

        Optional<String> empty = Optional.ofNullable(null);
        System.out.println(empty);
    }
// 輸出
Optional[emanjusaka]
Optional.empty

2、判斷方法

isPresent()

如果存在值則返回 true,否則返回 false。

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.ofNullable("emanjusaka");
        System.out.println(emanjusaka);
        System.out.println(emanjusaka.isPresent());
        Optional<String> empty = Optional.ofNullable(null);
        System.out.println(empty);
        System.out.println(empty.isPresent());
    }
//輸出
Optional[emanjusaka]
true
Optional.empty
false

?ifPresent(Consumer<? super T> consumer)??

如果存在值,則使用該值調(diào)用指定的消費(fèi)者,否則什么都不做。

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.of("emanjusaka");
        Consumer<String> consumer = s -> {
            s = "hello " + s;
            System.out.println(s);
        };
        System.out.println(emanjusaka);
        emanjusaka.ifPresent(consumer);
    }
// 輸出
Optional[emanjusaka]
hello emanjusaka

一般用于判斷 Optional 是否為空,并在不為空的情況下執(zhí)行相應(yīng)的操作。

3、獲取方法

get()

如果這個(gè) Optional 中存在一個(gè)值,則返回該值,否則拋出 NoSuchElementException。

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.ofNullable("emanjusaka");
        System.out.println(emanjusaka);
        System.out.println(emanjusaka.get());
        Optional<String> empty = Optional.ofNullable(null);
        System.out.println(empty);
        System.out.println(empty.get());
    }
// 輸出
Optional[emanjusaka]
emanjusaka
Optional.empty
Exception in thread "main" java.util.NoSuchElementException: No value present
    at java.util.Optional.get(Optional.java:135)
    at org.example.Main.main(Main.java:13)

filter(Predicate<? super T> predicate)

如果存在一個(gè)值,并且該值與給定的過濾條件匹配,則返回一個(gè)描述該值的 Optional,否則返回一個(gè)空的 Optional。

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.of("emanjusaka");
        System.out.println(emanjusaka);
        System.out.println(emanjusaka.filter(s -> {
            return "emanjusaka".equals(s);
        }));
        System.out.println(emanjusaka.filter(s -> false));
    }
// 輸出
Optional[emanjusaka]
Optional[emanjusaka]
Optional.empty

map(Function<? super T, ? extends U> mapper)

如果存在值,則將提供的映射函數(shù)應(yīng)用于該值,如果結(jié)果為非 null,則返回一個(gè)描述結(jié)果的 Optional。否則返回空的 Optional。

public static void main(String[] args) {
        User user = new User();
        user.setName("emanjusaka");
        Optional<User> optional = Optional.of(user);
        System.out.println(optional);
        System.out.println(optional.map(User::getName));
        User userEmpty = new User();
        Optional<User> optionalEmpty = Optional.of(userEmpty);
        System.out.println(optionalEmpty);
        System.out.println(optionalEmpty.map(User::getName));
    }
    private static class User {
        private String name;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
// 輸出
Optional[org.example.Main$User@2503dbd3]
Optional[emanjusaka]
Optional[org.example.Main$User@6d03e736]
Optional.empty

flatMap(Function<? super T, Optionalu> mapper)

如果存在值,請(qǐng)將提供的 Optional 方位映射函數(shù)應(yīng)用于該值,返回該結(jié)果,否則返回空的 Optional。此方法類似于map(Function),但提供的 mapper 的結(jié)果已經(jīng)是 Optional,并且如果調(diào)用,flatMap 不會(huì)用額外的 Optional 包裝它。

public static void main(String[] args) {
        User user = new User();
        user.setName("emanjusaka");
        user.setAge(Optional.of(35));
        Optional<User> optional = Optional.of(user);
        System.out.println(optional);
        System.out.println(optional.map(User::getAge));
        System.out.println(optional.flatMap(User::getAge));
    }
    private static class User {
        private String name;
        private Optional<Integer> age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Optional<Integer> getAge() {
            return age;
        }
        public void setAge(Optional<Integer> age) {
            this.age = age;
        }
    }
// 輸出
Optional[org.example.Main$User@2503dbd3]
Optional[Optional[35]]
Optional[35]

這個(gè)例子中體現(xiàn)出了 map 和 flatMap 方法的區(qū)別,map 方法會(huì)在返回時(shí)用 Optional 進(jìn)行包裝而 flatMap 方法不會(huì)再進(jìn)行額外的包裝。

orElse(T other)

如果存在這個(gè)值則返回這個(gè)值,否則返回傳入的值 other

public static void main(String[] args) {
        Optional<String> optional = Optional.of("emanjusaka");
        System.out.println(optional);
        System.out.println(optional.orElse(null));
        Optional<String> optionalEmpty = Optional.ofNullable(null);
        System.out.println(optionalEmpty);
        System.out.println(optionalEmpty.orElse("empty"));
    }
// 輸出
Optional[emanjusaka]
emanjusaka
Optional.empty
empty

orElseGet(Supplier<? extends T> other)

如果存在這個(gè)值則返回這個(gè)值,否則調(diào)用 other 并返回該調(diào)用的結(jié)果。

public static void main(String[] args) {
        Optional<String> optional = Optional.of("emanjusaka");
        System.out.println(optional);
        System.out.println(optional.orElseGet(() -> "hello emanjusaka"));
        Optional<String> optionalEmpty = Optional.ofNullable(null);
        System.out.println(optionalEmpty);
        System.out.println(optionalEmpty.orElseGet(() -> "hello emanjusaka"));
    }
// 輸出
Optional[emanjusaka]
emanjusaka
Optional.empty
hello emanjusaka

orElseThrow(Supplier? extends X exceptionSupplier)

返回包含的值(如果存在),否則拋出由所提供創(chuàng)建的異常。

public static void main(String[] args) {
        Optional<String> optionalEmpty = Optional.ofNullable(null);
        System.out.println(optionalEmpty);
        System.out.println(optionalEmpty.orElseThrow(ArithmeticException::new));
    }
// 輸出
Optional.empty
Exception in thread "main" java.lang.ArithmeticException
    at java.util.Optional.orElseThrow(Optional.java:290)
    at org.example.Main.main(Main.java:9)

二、Optional 中方法的區(qū)別

1、map 和 flatMap 方法的區(qū)別

  • map 方法會(huì)在返回時(shí)用 Optional 進(jìn)行包裝而 flatMap 方法不會(huì)再進(jìn)行額外的包裝。

2、orElse 和 orElseGet 方法的區(qū)別

  • orElse():如果有值則將其返回,否則返回指定的 other。
  • orElseGet():如果有值則將其返回,否則調(diào)用函數(shù) other 并將其返回調(diào)用結(jié)果。
  • orElse() 方法在 Optional 值為非空時(shí),也會(huì)計(jì)算傳入的參數(shù),而 orElseGet() 方法只有在 Optional 值為空時(shí)才會(huì)執(zhí)行傳入的函數(shù)。

如果是傳值可以選用 orElse(),如果傳入的是方法選用orElseGet()??。

三、總結(jié)

在使用 Optional 時(shí)我覺得應(yīng)該盡量避免一些情況:

  • 永遠(yuǎn)不要通過返回 Optional 的方法返回一個(gè)空值:它破壞 Optional 設(shè)計(jì)的初衷。
  • 并不是所有的返回類型都能從 Optional 的處理中獲益。容器類型,包括集合、映射、Stream、數(shù)組和 Optional,不應(yīng)該封裝在 Optional 中。與其返回一個(gè)空的 Optional<List<T>> ,不還如返回一個(gè) 空的 List<T> 。
  • 除了「次要基本類型(minor primitive types)」Boolean,Byte,Character,Short 和 Float 之外,永遠(yuǎn)不應(yīng)該返回裝箱的基本類型 的 Optional。

總之,如果發(fā)現(xiàn)自己編寫的方法不能總是返回值,并且認(rèn)為該方法的用戶在每次調(diào)用時(shí)考慮這種可能性很重要,那么或許應(yīng)該返回一個(gè) Optional 的方法。但是,應(yīng)該意識(shí)到,返回 Optional 會(huì)帶來實(shí)際的性能后果;對(duì)于性能關(guān)鍵的方法,最好返回 null 或拋出異常。最后,除了作為返回值之外,不應(yīng)該在任何其他地方中使用 Optional。

使用 Optional 時(shí)要注意,我認(rèn)為它并不能完全避免空指針。如果這個(gè)值是 null ,不做額外的判斷,直接使用還是會(huì)有空指針的問題。使用 Optional 的好處是它可以幫助我們簡化判空的操作,簡潔我們的代碼。用了 Optional 最后拿結(jié)果的時(shí)候還是要小心的,盲目 get 一樣會(huì)拋錯(cuò)。

參考文獻(xiàn)

《Effective Java》jdk11的文檔

以上就是JDK8新出Optional類的方法探索與思考分析的詳細(xì)內(nèi)容,更多關(guān)于JDK8 Optional類的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java實(shí)現(xiàn)桌面右下角彈窗效果

    java實(shí)現(xiàn)桌面右下角彈窗效果

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)桌面右下角彈窗效果,模仿類似于qq消息彈窗,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • springboot返回html和jsp的方法示例

    springboot返回html和jsp的方法示例

    這篇文章主要介紹了springboot返回html和jsp的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • mybatis-plus自帶QueryWrapper自定義sql實(shí)現(xiàn)復(fù)雜查詢實(shí)例詳解

    mybatis-plus自帶QueryWrapper自定義sql實(shí)現(xiàn)復(fù)雜查詢實(shí)例詳解

    MyBatis-Plus是一個(gè)MyBatis(opens new window)的增強(qiáng)工具,在 MyBatis的基礎(chǔ)上只做增強(qiáng)不做改變,MyBatis可以無損升級(jí)為MyBatis-Plus,這篇文章主要給大家介紹了關(guān)于mybatis-plus自帶QueryWrapper自定義sql實(shí)現(xiàn)復(fù)雜查詢的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • java開發(fā)flyway的方法

    java開發(fā)flyway的方法

    這篇文章主要介紹了java開發(fā)flyway的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • IDEA新建javaWeb以及Servlet簡單實(shí)現(xiàn)小結(jié)

    IDEA新建javaWeb以及Servlet簡單實(shí)現(xiàn)小結(jié)

    這篇文章主要介紹了IDEA新建javaWeb以及Servlet簡單實(shí)現(xiàn)小結(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-11-11
  • java鏈表的頭插法和尾插法詳解

    java鏈表的頭插法和尾插法詳解

    本文介紹了鏈表的基本概念,包括節(jié)點(diǎn)類Listnode和鏈表類Linklist,頭插法和尾插法是兩種常見的插入節(jié)點(diǎn)的方法,分別通過頭指針和游標(biāo)來實(shí)現(xiàn),通過示例代碼和測試,展示了鏈表的創(chuàng)建和操作過程
    2024-12-12
  • 淺談Java中的橋接方法與泛型的逆變和協(xié)變

    淺談Java中的橋接方法與泛型的逆變和協(xié)變

    對(duì)應(yīng)于Java當(dāng)中,協(xié)變對(duì)應(yīng)的就是<? extends XXX>,而逆變對(duì)應(yīng)的就是<? super XXX>,本文詳細(xì)的介紹了Java中的橋接方法與泛型的逆變和協(xié)變,感興趣的可以了解一下
    2022-04-04
  • Java中Date和Calendar常用方法

    Java中Date和Calendar常用方法

    這篇文章主要為大家詳細(xì)介紹了Java中Date和Calendar常用用法,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Java在Excel中創(chuàng)建多級(jí)分組、折疊或展開分組的實(shí)現(xiàn)

    Java在Excel中創(chuàng)建多級(jí)分組、折疊或展開分組的實(shí)現(xiàn)

    這篇文章主要介紹了Java在Excel中創(chuàng)建多級(jí)分組、折疊或展開分組的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • 淺談解決Hibernate懶加載的4種方式

    淺談解決Hibernate懶加載的4種方式

    這篇文章主要介紹了淺談解決Hibernate懶加載的4種方式,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12

最新評(píng)論