Optional
前言
我的使用
package yimeng;
import com.ruoyi.RuoYiApplication;
import com.ruoyi.common.core.domain.entity.SysUser;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.*;
@SpringBootTest(classes = RuoYiApplication.class)
public class MyTest2 {
@Test
public void testOptional() {
List<SysUser> list=new ArrayList<>();
SysUser sysUser1=new SysUser(1L,"張三");
SysUser sysUser2=new SysUser(1L,"李四");
SysUser sysUser3=new SysUser(3L,"王五");
list.add(sysUser1);
list.add(sysUser2);
list.add(sysUser3);
Optional<SysUser> optionalSysUser = list.stream().filter((item) -> item.getUserId().compareTo(1L) == 0L).findFirst();
SysUser sysUser = optionalSysUser.get();
System.out.println(sysUser);//打印了“張三”這個用戶
}
}
雨澤的使用
package yimeng;
import com.ruoyi.RuoYiApplication;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.system.mapper.SysUserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
@SpringBootTest(classes = RuoYiApplication.class)
public class MyTest2 {
@Resource
private SysUserMapper sysUserMapper;
@Test
public void testOptional2() {
SysUser sysUser = sysUserMapper.selectUserById(1L);
String s = Optional.ofNullable(sysUser)
.map(SysUser::getUserName)
.orElseThrow(() -> new RuntimeException("id是1L的用戶為null"));
System.out.println(s);
SysUser sysUser1 = sysUserMapper.selectUserById(100L);
Optional.ofNullable(sysUser1)
.map(SysUser::getUserName)
.orElseThrow(() -> new RuntimeException("id是100L的用戶為null或者名字為null"));
}
}
結(jié)果:
這里不知道他有沒有走map方法。
但是通過看源碼可以知道。其實他是走了map方法的,但是為什么沒有拋出空指針異常呢?你null.map()了。
因為他內(nèi)部把null轉(zhuǎn)換了一下,你Optional.ofNullable(sysUser)返回值不是null了。所以調(diào)用map方法不會出現(xiàn)空指針異常。如果sysUser是空,相當(dāng)于是返回一個private static final Optional<?> EMPTY = new Optional<>();
的東西。
然后用這個東西去調(diào)用map方法,map方法也是先看你是不是空對應(yīng)的Optional,看到是調(diào)用者是空對應(yīng)的Optional,也返回一個private static final Optional<?> EMPTY = new Optional<>();
,不會去執(zhí)行真正map()方法中的lambda表達(dá)式的,所以看起來像是跳過了map中的邏輯直接執(zhí)行了orElseThrow方法。
探測:
探測:
ofNullable()參數(shù)為null不拋出空指針異常的原因:
filter()參數(shù)為null拋出空指針異常的原因:
API詳細(xì)介紹
Optional 就相當(dāng)于是一個對象容器。
初始化方法
of(T t)
功能:創(chuàng)建Optional實例
注意:創(chuàng)建對象時傳入的參數(shù)不能為null。如果傳入?yún)?shù)為null,則拋出NullPointerException 。
@Test
public void test(){
// 創(chuàng)建Optional實例:參數(shù)非null
Optional<String> notNullOptional = Optional.of("xiaoxian");
System.out.println(notNullOptional);
// 創(chuàng)建Optional實例:參數(shù)為null,拋出 NullPointerException
try {
Optional<String> nullOptional = Optional.of(null);
} catch (NullPointerException e) {
System.out.println("【of()】" + e.getMessage());
// 輸出:java.lang.NullPointerException
e.printStackTrace();
}
}
探測:
探測:
探測:
ofNullable(T t)
功能:創(chuàng)建Optional實例
注意:如果指定的值為null,則返回一個空的Optional。
@Test
public void test(){
// ofNullable()與of()相似,區(qū)別在于:ofNullable()是可以接受參數(shù)為null的情況。
// 創(chuàng)建Optional實例:參數(shù)非null
Optional<String> notNullOptional = Optional.ofNullable("xiaoxian");
// 創(chuàng)建Optional實例:參數(shù)為null,不會報錯,返回一個空的Optional實例
Optional<String> nullOptional = Optional.ofNullable(null);
}
empty()
功能:創(chuàng)建空的Optional實例
@Test
public void test(){
Optional<String> emptyOptional = Optional.empty();
System.out.println(emptyOptional);
}
獲取
get()
@Test
public void test(){
Optional<String> notNullOptional = Optional.ofNullable("xiaoxian");
System.out.println(notNullOptional.get());
Optional<String> emptyOptional = Optional.empty();
System.out.println(emptyOptional.get());
}
get():獲取optional容器中的對象,當(dāng)optional 容器為空時報錯。返回值為容器中那個對象的類型。
探測:
因為get方法,返回的是Optional對象聲明時的那個泛型,不是返回一個Optional對象,所以get()后無法使用Optional的orElseThrow方法。
判斷
isPresent()
isPresent():判斷optional是否為空,如果空則返回false,否則返回true
@Test
public void test(){
// 創(chuàng)建Optional實例:參數(shù)非null
Optional<String> notNullOptional = Optional.ofNullable("xiaoxian");
// 創(chuàng)建Optional實例:參數(shù)為null,不會報錯,返回一個空的Optional實例
Optional<String> nullOptional = Optional.ofNullable(null);
// 輸出:true
System.out.println("【isPresent()】" + notNullOptional.isPresent());
// 輸出:false
System.out.println("【isPresent()】" + nullOptional.isPresent());
}
ifPresent(Consumer consumer)
ifPresent(Consumer c):如果optional不為空,則將optional中的對象傳給Comsumer函數(shù),去執(zhí)行對應(yīng)的方法。如果為空,不執(zhí)行什么操作。ifPresent方法的返回是void,所以也不會返回什么東西。
@Test
public void test(){
// 創(chuàng)建Optional實例:參數(shù)非null
Optional<String> notNullOptional = Optional.ofNullable("xiaoxian");
//如果實例值非null,就執(zhí)行l(wèi)ambda表達(dá)式,否則不處理
notNullOptional.ifPresent(s -> {
s = s + " love java";
// 輸出:xiaoxian love java
System.out.println(s);
});
}
Else相關(guān)
orElse()和orElseGet()
我們在初始化 Optional 對象的時候,有時候需要一個默認(rèn)值,這時orElse() 和 orElseGet() 方法就派上用場了(類似三目運(yùn)算符)。
orElse()功能:檢查Optional容器中的對象是否是null,如果非null,就返回這個對象。否則返回你自己指定的其它值。
@Test
public void test(){
String name = Optional.ofNullable("張三").orElse("沉默王二");
System.out.println(name); // 輸出:張三
String nullName = null;
String name1 = Optional.ofNullable(nullName).orElse("沉默王二");
System.out.println(name1); // 輸出:沉默王二
}
注意:是返回orElse方法不管,調(diào)用它的Optional是不是為空的容器,都會返回它聲明的泛型的對象。不是要以為Optional.ofNullable(“張三”).orElse(“沉默王二”);返回還是Optional對象哈??辞宄厦娴睦臃祷氐氖且粋€String,不是一個Optional對象哈。
orElseGet()功能:orElseGet() 方法與 orElse() 方法類似,但參數(shù)類型不同。orElseGet()方法的功能是,如果 Optional 容器中的對象為 null,則執(zhí)行參數(shù)中的lambda表達(dá)式的方法。
@Test
public void test(){
Optional<String> notNullOptional = Optional.ofNullable("xiaoxian");
Optional<String> nullOptional = Optional.ofNullable(null);
// orElseGet與orElse方法類似
// 區(qū)別在于:orElse傳入的是默認(rèn)值,orElseGet可以接收一個lambda表達(dá)式生成默認(rèn)值
//如果Optional實例值非null,返回Optional的值
// 輸出:xiaoxian
System.out.println("【orElseGet()】" + notNullOptional.orElseGet(() -> "Default Value"));
//如果Optional實例值為null,返回lambda表達(dá)式的值
// 輸出:Default Value
System.out.println("【orElseGet()】" + nullOptional.orElseGet(() -> "Default Value"));
}
從輸出結(jié)果以及代碼的形式上來看,這兩個方法極其相似,這不免引起我們的懷疑,Java 類庫的設(shè)計者有必要這樣做嗎?
假設(shè)現(xiàn)在有這樣一個獲取默認(rèn)值的方法,很傳統(tǒng)的方式
public static String getDefaultValue() { System.out.println("getDefaultValue"); return "沉默王二"; }
然后,通過 orElse() 方法和 orElseGet() 方法分別調(diào)用 getDefaultValue() 方法返回默認(rèn)值
public static void main(String[] args) { String name = null; System.out.println("orElse"); String name2 = Optional.ofNullable(name).orElse(getDefaultValue()); System.out.println("orElseGet"); String name3 = Optional.ofNullable(name).orElseGet(Demo::getDefaultValue); }
注:類名 :: 方法名是 Java 8 引入的語法,方法名后面是沒有 () 的,表明該方法并不一定會被調(diào)用
輸出結(jié)果如下所示:
orElse getDefaultValue orElseGet getDefaultValue
輸出結(jié)果是相似的,沒什么太大的不同,這是在 Optional 對象的值為 null 的情況下。假如 Optional 對象的值不為 null 呢?
public static void main(String[] args) { String name = "沉默王三"; System.out.println("orElse"); String name2 = Optional.ofNullable(name).orElse(getDefaultValue()); System.out.println("orElseGet"); String name3 = Optional.ofNullable(name).orElseGet(OrElseOptionalDemo::getDefaultValue); }
輸出結(jié)果如下所示:
orElse getDefaultValue orElseGet
在Optional容器中的對象不是null時,orElseGet() 并沒有去調(diào)用 getDefaultValue()方法,而orElse方法還是會去調(diào)用的,只是返回值沒有被使用而已。所以orElseGet方法的性能更佳。
直觀從語義上來看,get() 方法才是最正宗的獲取 Optional 對象值的方法,但很遺憾,該方法是有缺陷的,因為假如 Optional 容器中的值為 null,該方法會拋出 NoSuchElementException 異常。這完全與我們使用 Optional 類的初衷相悖。我們使用 Optional 其實就是為了防止異常。主要是防止空指針異常。如果是空的話,會把null轉(zhuǎn)換為對應(yīng)的Optional,所以不會出現(xiàn)空指針異常,你使用Optional的get方法,如果Option容器中的對象為null,就會拋出NoSuchElementException 異常,雖然這個不是空指針異常,但是也是異常,所以不建議使用Optional的get方法。
orElseThrow()
功能:檢查Optional容器中的實例是否為null,如果容器中實例值非null,就不做任何處理,如果是null,則拋異常Exception
@Test
public void test(){
Optional<String> notNullOptional = Optional.ofNullable("xiaoxian");
Optional<String> nullOptional = Optional.ofNullable(null);
// orElseThrow與orElse方法類似
// 區(qū)別在于:orElse傳入的是默認(rèn)值,orElseThrow會拋出他參數(shù)中的lambda表達(dá)式或方法生成的異常
try {
//如果Optional實例值非null,不做任何處理,不會執(zhí)行orElseThrow()內(nèi)的方法。
notNullOptional.orElseThrow(Exception::new);
} catch (Exception e) {
e.printStackTrace();
}
try {
//如果Optional實例值為null,會執(zhí)行orElseThrow()內(nèi)對象的方法。并且這個orElseThrow內(nèi)對象的方法必須是可以拋的,即異常對象。
nullOptional.orElseThrow(Exception::new);
} catch (Throwable e) {
// 輸出: null
System.out.println("【orElseThrow()】" + e.getMessage());
e.printStackTrace();
}
}
探測:
看到orElseThrow方法中的對象的get方法的返回值必須是一個可被拋出的對象,所以orElseThrow方法中對象的方法都是創(chuàng)建一個異常類。(Supplier他就一個方法,如果是lambda表達(dá)式,那么lambda表達(dá)式中的方法體就是這個get方法的方法體,這是lambda表達(dá)式的知識點。)
過濾
filter(Predicate p)
filter(Predicate p):如果optional容器中的對象不為空,則執(zhí)行斷言函數(shù)p,如果p的結(jié)果為true,則返回原本的optional,否則返回空的optional。如果optional容器中的對象為空,那么也返回空的Optional。
@Test
public void test(){
Optional<String> notNullOptional = Optional.ofNullable("xiaoxian");
//如果是空,就返回空Optional
Optional<String> nullOptional = Optional.ofNullable(null);
Optional<String> aaa = nullOptional.filter(item -> item.equals("kkk"));
System.out.println(aaa);
// 如果不是空,且滿足filter條件,則返回該Option容器中的對象實例,否則返回空Optional。value就是指Optional容器中的對象。
Optional<String> filterTrue = notNullOptional.filter((value) -> value.length() > 6);
//輸出:xiaoxian
System.out.println("【filter】" + filterTrue.orElse("不滿足filter條件"));
//如果不是空,且不滿足filter條件,則返回空Optional。value就是指Optional容器中的對象。
Optional<String> filterFalse = notNullOptional.filter((value) -> value.length() > 10);
//輸出:【filter】Optional.empty
System.out.println("【filter】" + filterFalse);
}
映射
map(Function<T, U> mapper)
map(Function<T, U> mapper):如果optional容器中對象不為空,則將optional中的對象 t 映射成另外一個對象 u,并將 u 存放到一個新的optional容器中。否則返回空Optional。
@Test
public void test(){
Optional<String> notNullOptional = Optional.ofNullable("xiaoxian");
//如果是空,就返回空Optional
Optional<String> nullOptional = Optional.ofNullable(null);
// 如果Optional實例值非null,執(zhí)行map(lambda表達(dá)式,任意類型),返回新的Optional實例
Optional<String> notNullToUpperCase = notNullOptional.map((value) -> value.toUpperCase());
// 輸出:map后是一個新的Optional對象
System.out.println(notNullOptional==notNullToUpperCase?"是一個對象":"map后是一個新的Optional對象");
// 輸出:XIAOXIAN
System.out.println("【map()】" + notNullToUpperCase.orElse("No value found"));
Optional<Integer> notNullToInteger = notNullOptional.map((value) -> 1);
// 輸出:1
System.out.println("【map()】" + notNullToInteger.orElse(2));
// 如果Optional實例值為null,不用執(zhí)行map(),返回空Optional
Optional<String> emptyToUpperCase = nullOptional.map((value) -> value.toUpperCase());
// 輸出:No value found
System.out.println("【map()】" + emptyToUpperCase.orElse("No value found"));
}
注意:如果map中的實參是一個null,那么也將會觸發(fā)空指針異常,導(dǎo)致后面的方法不會被執(zhí)行。比如:
@Test
public void test(){
SysUser sysUser1 = sysUserMapper.selectUserById(1L);
Optional.ofNullable(sysUser1)
.map(null)
.orElseThrow(() -> new RuntimeException("id是1L的用戶為null或者頭像為null"));
}
源碼解析:
flatMap(Function< T,Optional< U >> mapper)
flatMap():flatMap()與 map()類似,區(qū)別在于:他們傳入方法的lambda表達(dá)式的返回類型
map():lambda表達(dá)式返回值可以是任意類型,在map函數(shù)返回之前會包裝為Optional
flatMap:lambda表達(dá)式返回值必須是Optionl實例,不會自動把結(jié)果包裝為Optional,需要你手動把返回值封裝為Optional才行。文章來源:http://www.zghlxwxcb.cn/news/detail-822717.html
@Test
public void test(){
Optional<String> notNullOptional = Optional.ofNullable("xiaoxian");
//如果是空,就返回空Optional
Optional<String> nullOptional = Optional.ofNullable(null);
// flatMap()與 map()類似,區(qū)別在于:傳入方法的lambda表達(dá)式的返回類型
// map():lambda表達(dá)式返回值可以是任意類型,在map函數(shù)返回之前會包裝為Optional
// flatMap:lambda表達(dá)式返回值必須是Optionl實例,不會把結(jié)果包裝為Optional
//如果Optional容器中對象的值非null,執(zhí)行flatMap(lambda表達(dá)式),但是注意得返回一個Optional類型的返回值
Optional<String> notNullToUpperCase = notNullOptional.flatMap((value) -> Optional.of(value.toUpperCase()));
// 輸出:XIAOXIAN
System.out.println("【flatMap()】" + notNullToUpperCase.orElse("No value found"));
//如果Optional容器中實例的值為null,不用執(zhí)行flatMap(lambda表達(dá)式),返回空Optional
Optional<String> optional = nullOptional.flatMap((value) -> Optional.of(value.toUpperCase()));
// 輸出:No value found
System.out.println("【flatMap()】" + optional.orElse("No value found"));
}
文章來源地址http://www.zghlxwxcb.cn/news/detail-822717.html
使用推薦
1、如果實例值不為null,就返回值,否則為null
// 之前寫法
User user1 = userOptional.isPresent() ? userOptional.get() : null;
// 推薦寫法
User user2 = userOptional.orElse(null);
2、如果實例值不為null,就返回值,否則進(jìn)行指定操作
// 之前寫法
User user3 = userOptional.isPresent() ? userOptional.get(): getUser();
// 推薦寫法
User user4 = userOptional.orElseGet(() -> getUser());
3、如果實例值不為null,就進(jìn)行指定操作
// 之前寫法
if (userOptional.isPresent()) {
System.out.println(userOptional.get());
}
// 推薦寫法
userOptional.ifPresent(System.out::println);
// 之前寫法
if (userOptional.isPresent()) {
getUser();
}
// 推薦寫法
userOptional.ifPresent(e->getUser());
4、如果實例值不為null,就獲取實例值,并進(jìn)行指定操作
// 之前寫法
List<String> list = null;
if(userOptional.isPresent()) {
list = userOptional.get().getCourseList();
} else {
list = Collections.emptyList();
}
// 推薦寫法
list = userOptional.map(u -> u.getCourseList()).orElse(Collections.emptyList());
// 之前寫法
getName(new User("xiaoxian"));
// 推薦寫法
getNameNew(new User("xiaoxian"));
public static String getName(User user){
if(user != null) {
String name = user.getName();
if(name != null) {
return name.toUpperCase();
} else {
return null;
}
} else {
return null;
}
}
public static String getNameNew(User user){
Optional<User> userOptional = Optional.ofNullable(user);
return userOptional.map(u -> u.getName())
.map(name -> name.toUpperCase())
.orElse(null);
}
推薦示例代碼
import java.util.Collections;
import java.util.List;
public class UseOptional {
public static User getUser() {
return new User("xiaoxian");
}
public static void main(String[] args) {
Optional<User> userOptional = Optional.of(new User("xiaoxian"));
// 之前寫法
User user1 = userOptional.isPresent() ? userOptional.get() : null;
// 推薦寫法
User user2 = userOptional.orElse(null);
// 之前寫法
User user3 = userOptional.isPresent() ? userOptional.get() : getUser();
// 推薦寫法
User user4 = userOptional.orElseGet(() -> getUser());
// 之前寫法
if (userOptional.isPresent()) {
System.out.println(userOptional.get());
}
// 推薦寫法
userOptional.ifPresent(System.out::println);
// 之前寫法
if (userOptional.isPresent()) {
getUser();
}
// 推薦寫法
userOptional.ifPresent(e -> getUser());
// 之前寫法
List<String> list = null;
if (userOptional.isPresent()) {
list = userOptional.get().getCourseList();
} else {
list = Collections.emptyList();
}
// 推薦寫法
list = userOptional.map(u -> u.getCourseList()).orElse(Collections.emptyList());
// 之前寫法
getName(new User("xiaoxian"));
// 推薦寫法
getNameNew(new User("xiaoxian"));
}
public static String getName(User user) {
if (user != null) {
String name = user.getName();
if (name != null) {
return name.toUpperCase();
} else {
return null;
}
} else {
return null;
}
}
public static String getNameNew(User user) {
Optional<User> userOptional = Optional.ofNullable(user);
return userOptional.map(u -> u.getName()).map(name -> name.toUpperCase()).orElse(null);
}
}
class User {
public String name;
public List<String> courseList;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public List<String> getCourseList() {
return courseList;
}
}
到了這里,關(guān)于Optional的使用(代替if判斷是否為空)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!