Java中Optional的orElse操作及orElse與orElseGet的區(qū)別詳解
1. 大概說(shuō)明
這篇文章的目的是為了說(shuō)明:
- orElse 如何使用
- orElseGet 如何使用
- 兩者的區(qū)別
備注:orElse 可能導(dǎo)致 NullPointerException,當(dāng) orElse 的參數(shù)是間接計(jì)算得來(lái)的時(shí)候。雖然這種說(shuō)法有點(diǎn)牽強(qiáng)(因?yàn)椴⒉皇莖rElse導(dǎo)致了空指針異常),但是使用 orElseGet 確實(shí)可以避免這種情況。
2. 詳細(xì)分析
2.1 .orElse 操作
先看個(gè)例子:
Optional<String> optional = Optional.empty(); System.out.println(optional.isPresent); // ---->輸出:false // 返回 false,表示 Optional 里沒(méi)有值。解析:
Optional.empty()代表 一個(gè)空的 Optional 實(shí)例,即Optional沒(méi)有值。Optional.ofNullable(null)等價(jià)于Optional.empty()。
2.2 .orElse 的作用:避免空指針異常
- 如果
Optional為空(即Optional.empty()),就返回orElse()里提供的默認(rèn)值。 - 如果
Optional有值,就直接返回這個(gè)值,不執(zhí)行orElse()提供的默認(rèn)值。
注意:不管 Optional 為不為空,這個(gè)值都會(huì)創(chuàng)建,只不過(guò)為空時(shí),才使用
// 舉例:當(dāng)Optional為空時(shí),orElse()才會(huì)觸發(fā)
String result = Optional.ofNullable(null)
.orElse("默認(rèn)值");
System.out.println(result); // ---->輸出:默認(rèn)值
// 再舉個(gè)例子:
Map<Long, List<String>> map = new HashMap<>();
map.put(1L, Arrays.asList("A", "B", "C"));
List<String> result = Optional.ofNullable(map.get(1L))
.orElse(Collections.emptyList()); // 為null就返回 空列表
System.out.println(result); // ---->輸出:[A, B, C] (orElse() 沒(méi)起作用)
2.3 為什么要用?
List<String> result = Optional.ofNullable(map.get(0L))
.orElse(Collections.emptyList())
.stream();
如果 map.get(0L) == null,那么:
- 不加
.orElse(Collections.emptyList())→.stream()會(huì)報(bào)NullPointerException? - 加了
.orElse(Collections.emptyList())→.stream()能正常執(zhí)行 ?
2.4 orElseGet如何使用
再來(lái)看看 orElseGet 中如何使用:
orElseGet 作用:獲取數(shù)據(jù)并且設(shè)置數(shù)據(jù)為空時(shí)的默認(rèn)值。如果數(shù)據(jù)不為空就能獲取到該數(shù)據(jù);如果為空則返回傳入的參數(shù)來(lái)創(chuàng)建對(duì)象。
具體的使用案例可看下圖:


2.5 orElse和orElseGet的區(qū)別
orElse() 和 orElseGet() 都是Optional 類(lèi)中的方法,用于在 Optional 為空時(shí)提供默認(rèn)值。但它們的區(qū)別在于 默認(rèn)值的獲取方式:
1、orElse(T other)
- 直接傳遞一個(gè)默認(rèn)值
- 即使
Optional里有值,也會(huì)創(chuàng)建 other 對(duì)象,但不會(huì)使用它 - 適用于默認(rèn)值創(chuàng)建代價(jià)較低的情況
2、orElseGet(Supplier<? extends T> supplier)
- 傳遞的是一個(gè)
Supplier(懶加載:只有需要的時(shí)候才會(huì)創(chuàng)建)接口,它是一個(gè)函數(shù)式接口,形式是這樣的:()->{ return computedResult },即入?yún)榭眨蟹祷刂担ㄈ我忸?lèi)型的) - 僅當(dāng)
Optional為空時(shí)才會(huì)執(zhí)行supplier.get(),不會(huì)提前創(chuàng)建默認(rèn)值 - 適用于默認(rèn)值創(chuàng)建代價(jià)較高的情況
看個(gè)例子:
class User {
// 中文名
private String chineseName;
// 英文名
private EnglishName englishName;
}
class EnglishName {
// 全名
private String fullName;
// 簡(jiǎn)寫(xiě)
private String shortName;
}
假如我們現(xiàn)在有 User 類(lèi),用戶(hù)注冊(cè)賬號(hào)時(shí),需要提供自己的中文名或英文名,或都提供,我們抽象出一個(gè)EnglishName 類(lèi),它包含英文名的全名和簡(jiǎn)寫(xiě)(因?yàn)橛械挠⑽拿_實(shí)太長(zhǎng)了)?,F(xiàn)在,我們希望有一個(gè)User.getName() 方法,它可以像下面這樣實(shí)現(xiàn):
class User {
// ... 之前的內(nèi)容
public String getName1() {
return Optional.ofNullable(chineseName)
.orElse(englishName.getShortName());
}
public String getName2() {
return Optional.ofNullable(chineseName)
.orElseGet(() -> englishName.getShortName());
}
}
寫(xiě)了兩個(gè)版本,分別使用 orElse 和 orElseGet?,F(xiàn)在,你可以看出 getName1() 方法有什么風(fēng)險(xiǎn)了嗎?它會(huì)出現(xiàn)空指針異常嗎?----> 是的。當(dāng)用戶(hù)只提供了中文名時(shí),此時(shí) englishName 屬性是 null,但是在 orElse 中,englishName.getShortName()總是會(huì)執(zhí)行。而在 getName2() 中,這個(gè)風(fēng)險(xiǎn)卻沒(méi)有。
再舉個(gè)例子:
public class Test {
public static void main(String[] args) {
System.out.println("orElse() 的情況:");
String result1 = Optional.ofNullable("實(shí)際值")
.orElse(test2());
System.out.println("最終結(jié)果: " + result1);
System.out.println("orElseGet() 的情況:");
String result2 = Optional.ofNullable("實(shí)際值")
.orElseGet(() -> test2());
System.out.println("最終結(jié)果: " + result2);
}
public static String test2() {
System.out.println("執(zhí)行昂貴的計(jì)算...");
return "昂貴默認(rèn)值";
}
}
輸出:
orElse() 的情況:
執(zhí)行昂貴的計(jì)算...
最終結(jié)果: 實(shí)際值orElseGet() 的情況:
最終結(jié)果: 實(shí)際值
總結(jié)
到此這篇關(guān)于Java中Optional的orElse操作及orElse與orElseGet區(qū)別詳解的文章就介紹到這了,更多相關(guān)Java Optional的orElse操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
eclipse springboot工程打war包方法及再Tomcat中運(yùn)行的方法
這篇文章主要介紹了eclipse springboot工程打war包方法及再Tomcat中運(yùn)行的方法,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08
SpringBoot+aop實(shí)現(xiàn)主從數(shù)據(jù)庫(kù)的讀寫(xiě)分離操作
讀寫(xiě)分離的作用是為了緩解寫(xiě)庫(kù),也就是主庫(kù)的壓力,但一定要基于數(shù)據(jù)一致性的原則,就是保證主從庫(kù)之間的數(shù)據(jù)一定要一致,這篇文章給大家介紹SpringBoot+aop實(shí)現(xiàn)主從數(shù)據(jù)庫(kù)的讀寫(xiě)分離操作,感興趣的朋友跟隨小編一起看看吧2024-03-03
SpringBoot Java后端實(shí)現(xiàn)okhttp3超時(shí)設(shè)置的方法實(shí)例
Okhttp的使用沒(méi)有httpClient廣泛,網(wǎng)上關(guān)于Okhttp設(shè)置代理的方法很少,下面這篇文章主要給大家介紹了關(guān)于SpringBoot Java后端實(shí)現(xiàn)okhttp3超時(shí)設(shè)置的相關(guān)資料,需要的朋友可以參考下2021-10-10
MyBatisPlus條件構(gòu)造器的實(shí)現(xiàn)示例
本文主要介紹了MyBatisPlus條件構(gòu)造器的實(shí)現(xiàn)示例,主要包括了QueryWrapper,UpdateWrapper,LambdaQueryWrapper,LambdaUpdateWrapper這四種,具有一定的參考價(jià)值,感興趣的可以了解下2023-12-12
淺析Java數(shù)據(jù)庫(kù)操作工具包jOOQ的使用
jOOQ?是一個(gè)輕量級(jí)的?Java?ORM(對(duì)象關(guān)系映射)框架,可用來(lái)構(gòu)建復(fù)雜的?SQL?查詢(xún),這篇文章主要來(lái)和大家介紹一下jOOQ的使用,需要的可以參考下2024-04-04

