自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

告別空指針,Optional的最佳使用姿勢(shì)!

開(kāi)發(fā) 項(xiàng)目管理
在實(shí)際使用的時(shí)候,還得結(jié)合具體的場(chǎng)景進(jìn)行合理選擇,有時(shí)候并不是全部采用Optional?來(lái)解決NPE?異常代碼才更加優(yōu)雅,比如當(dāng)前對(duì)象比較簡(jiǎn)單,就是一個(gè)簡(jiǎn)單判斷,通過(guò)obj != null足以解決問(wèn)題。

一、背景介紹

NullPointerException,中文名:空指針異常,也簡(jiǎn)稱(chēng) NPE,是軟件系統(tǒng)中最常見(jiàn)的錯(cuò)誤異常之一。

很久以前 Google Guava 項(xiàng)目引入了Optional作為解決空指針異常的一種方式,不贊成寫(xiě)過(guò)多的代碼來(lái)顯式檢查null,以期望程序員寫(xiě)出整潔同時(shí)可讀性更高的代碼。

受 Google Guava 的影響,Optional 現(xiàn)在也成為了Java 8 及以上庫(kù)代碼的一部分。

在介紹Optional技術(shù)之前,我們不禁會(huì)發(fā)出一個(gè)疑問(wèn):為什么谷歌不贊成寫(xiě)過(guò)多的代碼來(lái)顯式檢查null?

下面是某個(gè)常見(jiàn)的參數(shù)判空代碼,樣例如下。

// 判斷行政區(qū)是否為空
if(country != null){
    // 判斷行政區(qū)的上一級(jí),行政城市是否為空
    if(country.getCity() != null){
        // 判斷行政城市的上一級(jí),行政省是否為空
        if(country.getCity().getProvince() != null){
            // 獲取對(duì)應(yīng)的行政省相關(guān)的數(shù)據(jù)
            return country.getCity().getProvince().getName();
        }
    }
}

這還是最普通的三層判斷,假如有很大一段業(yè)務(wù)邏輯處理的時(shí)候,你會(huì)發(fā)現(xiàn)代碼不光看起來(lái)很臃腫,并且難以閱讀,可讀性很差!

如果調(diào)整為使用Optional來(lái)編寫(xiě)的話,可以轉(zhuǎn)換成如下寫(xiě)法:

// 獲取當(dāng)前行政區(qū)最頂級(jí)的省信息名稱(chēng)
String result  = Optional.ofNullable(country)
                .map(Country::getCity)
                .map(City::getProvince)
                .map(Province::getName)
                .orElse("error");

采用Optional來(lái)編程之后,整個(gè)代碼的可讀性和整潔度,是不是要干凈很多!

這也是為什么推薦大家使用Optional的原因啦!

當(dāng)然廢話也不多說(shuō),代碼直接擼起來(lái)!

二、案例實(shí)踐

在 JDK8 中,Optional 共有 12 個(gè)核心方法,下面我們一起來(lái)看看他們的用法!

2.1、empty()

empty 方法返回一個(gè)不包含值的 Optional 實(shí)例,單獨(dú)使用沒(méi)什么意義,主要和其他方法搭配使用。

Optional optional = Optional.empty();
System.out.println(optional);
-- 輸出結(jié)果
Optional.empty

2.2、of()

of 方法會(huì)返回一個(gè) Optional 實(shí)例,如果傳入的值非空,會(huì)返回包含指定值的對(duì)象;如果傳入空,會(huì)立刻拋出空指針異常。

// 非空情況下,會(huì)正常返回
Optional optional = Optional.of("hello world");
System.out.println(optional);
-- 輸出結(jié)果
Optional[hello world]
// 為空情況下,會(huì)拋空指針異常
Optional optional = Optional.of(null);
System.out.println(optional);
-- 輸出結(jié)果
Exception in thread "main" java.lang.NullPointerException
 at java.util.Objects.requireNonNull(Objects.java:203)
 at java.util.Optional.<init>(Optional.java:96)
 at java.util.Optional.of(Optional.java:108)

2.3、ofNullable()

ofNullable 方法會(huì)返回一個(gè) Optional 實(shí)例,如果傳入的值非空,會(huì)返回包含指定值的對(duì)象;如果傳入空,會(huì)返回不包含任何值的 empty 對(duì)象,也就是最開(kāi)始介紹的Optional.empty()對(duì)象。

// 非空情況下,會(huì)正常返回
Optional optional = Optional.ofNullable("hello world");
System.out.println(optional);
-- 輸出結(jié)果
Optional[hello world]
// 為空情況下,會(huì)返回 empty 對(duì)象
Optional optional = Optional.ofNullable(null);
System.out.println(optional);
-- 輸出結(jié)果
Optional.empty

2.4、isPresent()

isPresent 方法用來(lái)判斷實(shí)例是否包含值,如果包含非空值,返回 true,否則返回 false。

// 非空值,返回true
boolean rs1 =  Optional.ofNullable("hello").isPresent();
System.out.println(rs1);

// 空值,返回false
boolean rs2 =  Optional.ofNullable(null).isPresent();
System.out.println(rs2);
-- 輸出結(jié)果
true
false

2.5、get()

get 方法,如果實(shí)例包含非空值,則返回當(dāng)前值;否則拋出 NoSushElementException 異常。

// 非空值,返回當(dāng)前值
Object rs =  Optional.ofNullable("hello world").get();
System.out.println(rs);
-- 輸出結(jié)果
hello world
// 空值,會(huì)拋出 NoSushElementException 異常
Object rs =  Optional.ofNullable(null).get();
System.out.println(rs);
-- 輸出結(jié)果
Exception in thread "main" java.util.NoSuchElementException: No value present
 at java.util.Optional.get(Optional.java:135)

2.6、ifPresent()

ifPresent 方法作用是當(dāng)實(shí)例包含非空值時(shí),執(zhí)行傳入的 Consumer,比如調(diào)用一些其他方法;如果包含的值為空,不執(zhí)行任何操作。

Optional.ofNullable("hello world")
                .ifPresent( x -> {
                    System.out.println(x);
                });
-- 輸出結(jié)果
hello world

2.7、filter()

filter 方法用于過(guò)濾不符合條件的值,接收一個(gè)Predicate參數(shù),如果符合條件,會(huì)返回當(dāng)前的Optional實(shí)例,否則返回 empty 實(shí)例。

Optional.ofNullable("hello world")
                .filter(x -> x.contains("hello"))
                .ifPresent(x -> {
                    System.out.println(x);
                });
-- 輸出結(jié)果
hello world

2.8、map()

map 方法是鏈?zhǔn)秸{(diào)用避免空指針的核心方法,當(dāng)實(shí)例包含值時(shí),對(duì)值執(zhí)行傳入的Function函數(shù)接口方法,并返回一個(gè)代表結(jié)果值新的Optional實(shí)例,也就是將返回的結(jié)果再次包裝成Optional對(duì)象。

Optional.ofNullable("hello+world")
                .map(t -> {
                    if(t.contains("+")){
                        return t.replace("+", " ");
                    }
                    return t;
                }).ifPresent(t -> {
                    System.out.println(t);
                });
-- 輸出結(jié)果
hello world

2.9、flatMap()

flatMap 方法與 map 方法類(lèi)似,唯一不同的地方在于:需要手動(dòng)將返回的值,包裝成Optional實(shí)例,并且參數(shù)值不允許為空。

Optional.ofNullable("hello+world")
                .flatMap(t -> {
                    if(t.contains("+")){
                        t =  t.replace("+", " ");
                    }
                    // 不同之處
                    return Optional.of(t);
                }).ifPresent(t -> {
                    System.out.println(t);
                });
-- 輸出結(jié)果
hello world

2.10、orElse()

orElse 方法作用是如果實(shí)例包含非空值,那么返回當(dāng)前值;否則返回指定的默認(rèn)值。

Object rs =  Optional.ofNullable(null).orElse("null");
System.out.println(rs);
-- 輸出結(jié)果
null

2.11、orElseGet()

orElseGet 方法作用是如果實(shí)例包含非空值,返回這個(gè)值;否則,它會(huì)執(zhí)行作為參數(shù)傳入的Supplier函數(shù)式接口方法,并返回其執(zhí)行結(jié)果。

Object result = Optional.ofNullable(null)
                .orElseGet(() -> {
                    return "error";
                });
System.out.println(result);
-- 輸出結(jié)果
error

2.12、orElseThrow()

orElseThrow 方法作用是如果實(shí)例包含非空值,返回這個(gè)值;否則,它會(huì)執(zhí)行作為參數(shù)傳入的異常類(lèi)。

Optional.ofNullable(null)
                .orElseThrow(() -> new RuntimeException("參數(shù)為空"));
-- 輸出結(jié)果
Exception in thread "main" java.lang.RuntimeException: 參數(shù)為空
 at com.x.x.x.x.OptionalTest.lambda$main$10(OptionalTest3.java:144)
 at java.util.Optional.orElseThrow(Optional.java:290)

三、小結(jié)

以上就是 JDK8 新增的Optional類(lèi)的常用方法總結(jié),其中ofNullable、map和orElse方法搭配使用的最多。

另外orElse、orElseGet、orElseThrow區(qū)別如下:

  • orElse:如果實(shí)例包含空值,返回傳入指定的值
  • orElseGet:如果實(shí)例包含空值,返回傳入的方法中返回值
  • orElseThrow:如果實(shí)例包含空值,返回指定的異常類(lèi)型

在實(shí)際使用的時(shí)候,還得結(jié)合具體的場(chǎng)景進(jìn)行合理選擇,有時(shí)候并不是全部采用Optional來(lái)解決NPE異常代碼才更加優(yōu)雅,比如當(dāng)前對(duì)象比較簡(jiǎn)單,就是一個(gè)簡(jiǎn)單判斷,通過(guò)obj != null足以解決問(wèn)題。

因此在保證業(yè)務(wù)功能的正確和穩(wěn)定性的基礎(chǔ)之上,適當(dāng)?shù)倪x擇相關(guān)的工具來(lái)優(yōu)化代碼的整潔度和可讀性,更能發(fā)揮出錦上添花的效果!

責(zé)任編輯:武曉燕 來(lái)源: 潘志的研發(fā)筆記
相關(guān)推薦

2023-10-08 11:09:22

Optional空指針

2024-02-28 09:03:20

Optional空指針Java

2024-02-01 12:09:17

Optional容器null

2024-08-12 08:28:35

2023-08-04 08:52:52

Optional消滅空指針

2024-10-15 15:58:11

2025-02-27 09:39:56

JavaJava 8對(duì)象

2023-11-14 08:15:49

OptionalJava

2021-11-15 06:56:45

系統(tǒng)運(yùn)行空指針

2022-01-19 09:00:00

Java空指針開(kāi)發(fā)

2024-05-11 15:08:33

JavaScriptJava指針

2017-02-23 15:37:44

OptionObject容器

2020-12-28 06:20:27

OptionalTryjava

2018-05-28 15:34:12

數(shù)字營(yíng)銷(xiāo)

2017-09-23 15:28:32

JavaOptional方法

2017-07-10 13:09:45

前端Flexbox

2025-01-17 09:11:51

2020-11-02 07:43:33

前端空指針數(shù)據(jù)

2022-01-04 23:13:57

語(yǔ)言PanicGolang

2024-03-11 04:00:00

C#除List遍歷
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)