參考的博客寫在前面吧,感覺(jué)沒(méi)他們寫的好
【java8新特性】Optional詳解 - 簡(jiǎn)書 (jianshu.com)
理解、學(xué)習(xí)與使用 Java 中的 Optional - 張伯雨 - 博客園 (cnblogs.com)
一、為什么要引入Optional
? 下面這代碼,我們?cè)L問(wèn)任何對(duì)象或?qū)傩?,都有可能因?yàn)槟硞€(gè)對(duì)象為null導(dǎo)致NullPointerException
String result = school.getStudent().getA();
? 為了解決NullPointException(NPE)問(wèn)題,一般的我們采用逐個(gè)判斷是否為null再繼續(xù)下面的業(yè)務(wù)邏輯,如果需要判斷的對(duì)象很多,代碼看起來(lái)很多,很冗余。如下:
原先的避免NPE的方式
// 判斷每一層是否為空
if(school==null){
result = "error";
}else if(school.getStudent()==null){
result = "error";
}else if(school.getStudent().getA()==null){
result = "error";
}else {
result = school.getStudent().getA();
}
System.out.println(result);
使用Optional的方式
//直接構(gòu)造Optional并返回想要的結(jié)果
String result = Optional.ofNullable(school)
.map(School::getStudent)
.map(Student::getA)
.orElse("error");
System.out.println(result);
? 對(duì)比以上兩種方式,可以明顯的看出使用Optional的代碼更加簡(jiǎn)潔,不羅嗦,在orElse中可以直接將特殊情況返回,下面介紹Optional的具體用法。
二、Optional的使用
? 先看看Optional的部分源碼:
private static final Optional<?> EMPTY = new Optional<>();
private final T value;
private Optional() {
this.value = null;
}
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
這里可以看出,Optional的構(gòu)造函數(shù)都是私有,因此類外部不能顯示的使用new Optional()的方式來(lái)創(chuàng)建Optional對(duì)象,但是Optional類提供了三個(gè)靜態(tài)方法來(lái)創(chuàng)建Optional對(duì)象,示例如下:
empty() 空的Optional對(duì)象
of(T value) 非空的Optional對(duì)象
ofNullable(T value) 允許空的Optional對(duì)象
Optional<String> optStr = Optional.empty(); // 空
Student student = new Student();
Optional<Student> optStudent = Optional.of(student); // 非空
Optional<Student> optClass = Optional.ofNullable(student);// 可以空
構(gòu)建了Optional對(duì)象,下面來(lái)看看怎么使用Optional對(duì)象的接口,直接推薦兩種常用的使用方式:
第一種是使用orElse()接口,如果不為空,直接返回結(jié)果,為空返回orElse()中的內(nèi)容。看看源碼先:
public T orElse(T other) {
return value != null ? value : other;
}
再來(lái)看看orElse()的例子,將str包裝成Optional對(duì)象后,通過(guò)orElse()返回值。
String str = "hello";
String str1 = Optional.ofNullable(str).orElse("unknown");
第二種是使用ifPresent()接口,不為空則直接執(zhí)行ifpresent()內(nèi)的函數(shù),省去判空的步驟。看看源碼先:
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
源碼內(nèi)提到ifPresent()方法接受一個(gè)Consumer對(duì)象(消費(fèi)函數(shù)),如果包裝對(duì)象的值非空,運(yùn)行Consumer對(duì)象的accept()方法,(我的理解就是一個(gè)無(wú)返回值的函數(shù)而已),看看栗子:
Optional.ofNullable(student)
.ifPresent( u -> System.out.println("The student name is : " + u.getName()));
三、Optional的其他方法列舉
-
get()方法? 直接放回包裝對(duì)象的實(shí)際值,為null拋出異常
-
isPresent()方法? 判斷包裝對(duì)象是否為空
特別說(shuō)明的是,
get()方法并沒(méi)有直接對(duì)空對(duì)象有所處理,所以直接使用,仍然會(huì)有NPE問(wèn)題,于是,就有人想到:那我先用isPresent()先判空,再取值不就好了,于是就產(chǎn)生了如下的憨憨的代碼:Optional<Student> studentOpt = Optional.ofNullable(student); if(isPresent(studentOpt)){ String str = student.get(); }else{ String str = "unknown"; }上面的代碼違背了
Optional的初衷,應(yīng)使用orElse()方法改為如下:String str = Optional.ofNullable(student).orElse("unknown"); -
map()方法? 將Optional中的包裝對(duì)象經(jīng)過(guò)函數(shù)運(yùn)算后,并包裝成新的
Optional對(duì)象Optional<String> nameOpt = Optional.ofNullable(student).map(u -> u.getName());? 或?qū)懗上旅娴母袷?,更加?jiǎn)潔
Optional<String> nameOpt = Optional.ofNullable(student).map(Student::getName);?
map()鏈?zhǔn)秸{(diào)用,配合上orElse()就完成了文初的效果:String result = Optional.ofNullable(school) .map(School::getStudent) .map(Student::getA) .orElse("error"); System.out.println(result);
?