Optional類(lèi)的使用指南:解決空指針異常
在Java應(yīng)用程序中,空指針異常是導(dǎo)致程序失敗的最常見(jiàn)原因之一。為了更加優(yōu)雅地處理空指針異常,Java8引入了Optional類(lèi)庫(kù)。Optional實(shí)際上是一個(gè)容器,可以保存類(lèi)型T的值,或者僅僅保存null。通過(guò)使用Optional,我們能夠避免顯式進(jìn)行空值檢測(cè),使代碼更加清晰和健壯。
1.Optional類(lèi)是什么?
Optional 類(lèi)(java.util.Optional) 是一個(gè)容器類(lèi),它可以保存類(lèi)型T的值,代表這個(gè)值存在?;蛘邇H僅保存null,表示這個(gè)值不存在。原來(lái)用 null 表示一個(gè)值不存在,現(xiàn)在 Optional 可以更好的表達(dá)這個(gè)概念。并且可以避免空指針異常。
Optional提供很多有用的方法,這樣我們就不用顯式進(jìn)行空值檢測(cè)。
2. 創(chuàng)建Optional對(duì)象
Java8提供了兩種方式來(lái)創(chuàng)建Optional對(duì)象:
- Optional.of():of()不允許參數(shù)是null
- Optional.ofNullable():ofNullable()則沒(méi)有限制
// 參數(shù)不能是null
Optional optional1 = Optional.of(1);
// ofNullable參數(shù)可以是null
Optional optional2 = Optional.ofNullable(null);
// ofNullable參數(shù)也可以不是null
Optional optional3 = Optional.ofNullable(2);
3. 判斷值是否存在
使用isPresent()方法可以判斷Optional對(duì)象中的值是否存在。
Optional<Integer> optional1 = Optional.ofNullable(1);
Optional<Integer> optional2 = Optional.ofNullable(null);
System.out.println(optional1.isPresent()); // true
System.out.println(optional2.isPresent()); // false
4. 如果值存在,則執(zhí)行操作
ifPresent(Consumer consumer)方法,可以在Optional對(duì)象保存的值不為null時(shí)執(zhí)行指定的操作
Optional<Integer> optional1 = Optional.ofNullable(1);
Optional<Integer> optional2 = Optional.ofNullable(null);
// 如果不是null,調(diào)用Consumer
optional1.ifPresent(value -> System.out.println("value is " + value));
// null,不調(diào)用Consumer
optional2.ifPresent(value -> System.out.println("value is " + value));
輸出結(jié)果:
value is 1
5. 獲取值或默認(rèn)值
orElse(value)方法,可以在Optional對(duì)象保存的值不為null時(shí)返回原來(lái)的值,否則返回指定的默認(rèn)值
Optional<Integer> optional1 = Optional.ofNullable(1);
Optional<Integer> optional2 = Optional.ofNullable(null);
System.out.println(optional1.orElse(1000)); // 1
System.out.println(optional2.orElse(1000)); // 1000
6. 異常處理
orElseThrow()方法可以在值不存在時(shí)拋出異常,存在時(shí)什么都不做,類(lèi)似于Guava的Precoditions
Optional<Integer> optional1 = Optional.ofNullable(1);
Optional<Integer> optional2 = Optional.ofNullable(null);
optional1.orElseThrow(() -> new IllegalStateException());
try {
optional2.orElseThrow(() -> new IllegalStateException());
} catch (IllegalStateException e) {
e.printStackTrace();
}
7. 過(guò)濾和映射操作
Optional類(lèi)還提供了filter(Predicate)和map(Function)方法,用于對(duì)Optional對(duì)象中保存的值進(jìn)行過(guò)濾和映射
Optional<Integer> optional1 = Optional.ofNullable(1);
Optional<Integer> optional2 = Optional.ofNullable(null);
Optional<Integer> filter1 = optional1.filter(a -> a == null);
Optional<Integer> filter2 = optional1.filter(a -> a == 1);
Optional<Integer> filter3 = optional2.filter(a -> a == null);
System.out.println(filter1.isPresent()); // false
System.out.println(filter2.isPresent()); // true
System.out.println(filter2.get().intValue() == 1); // true
System.out.println(filter3.isPresent()); // false
Optional<String> str1Optional = optional1.map(a -> "key" + a);
Optional<String> str2Optional = optional2.map(a -> "key" + a);
System.out.println(str1Optional.get()); // key1
System.out.println(str2Optional.isPresent()); // false
8. flatMap操作
flatMap()方法與map()相似,不同之處在于flatMap()的mapping函數(shù)返回值必須是Optional類(lèi)型
Optional<Integer> optional1 = Optional.ofNullable(1);
Optional<Optional<String>> str1Optional = optional1.map(a -> Optional.of("key" + a));
Optional<String> str2Optional = optional1.flatMap(a -> Optional.of("key" + a));
System.out.println(str1Optional.get().get()); // key1
System.out.println(str2Optional.get()); // key1
9. Optional類(lèi)的方法總結(jié)
方法 | 描述 |
empty | 返回一個(gè)空的 Optional 實(shí)例 |
of | 將指定值用 Optional 封裝之后返回,如果該值為 null,則拋出一個(gè) NullPointerException 異常 |
ofNullable | 將指定值用 Optional 封裝之后返回,如果該值為 null,則返回一個(gè)空的 Optional 對(duì)象 |
orElse | 如果有值則將其返回,否則返回一個(gè)默認(rèn)值 |
orElseThrow | 如果有值則將其返回,否則拋出一個(gè)由指定的 Supplier 接口生成的異常 |
filter | 如果值存在并且滿足提供的斷言, 就返回包含該值的 Optional 對(duì)象;否則返回一個(gè)空的 Optional 對(duì)象 |
map | 如果值存在,就對(duì)該值執(zhí)行提供的 mapping 函數(shù)調(diào)用 |
flatMap | 如果值存在,就對(duì)該值執(zhí)行提供的 mapping 函數(shù)調(diào)用,返回一個(gè) Optional 類(lèi)型的值,否則就返 回一個(gè)空的 Optional 對(duì)象 |