日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
正確使用Java8中的Optional,它遠(yuǎn)比我們想象的優(yōu)秀

前言

我常說(shuō)學(xué)習(xí)一定要有目的,首先發(fā)現(xiàn)問(wèn)題,或者不便之處,然后尋找解決方案,解決方案可能有很多,我們要選擇好的方法來(lái)使用

10多年的多倫網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營(yíng)銷(xiāo)型網(wǎng)站建設(shè)的優(yōu)勢(shì)是能夠根據(jù)用戶(hù)設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整多倫建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)建站從事“多倫網(wǎng)站設(shè)計(jì)”,“多倫網(wǎng)站推廣”以來(lái),每個(gè)客戶(hù)項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

這篇文章介紹JDK8推出的Optional容器,會(huì)從以下幾點(diǎn)展開(kāi):

  • 現(xiàn)在編程的問(wèn)題或者說(shuō)痛點(diǎn)是什么
  • 通過(guò)案例演示:解決方案有哪些,Optional怎么解決
  • Optional系統(tǒng)用法
  • Optional的錯(cuò)誤用法
  • Optional總結(jié)

由此一起來(lái)認(rèn)識(shí)Optional的正確使用方式,遠(yuǎn)比我們想象的強(qiáng)大,好用,看很多文章和教程都在講API,個(gè)人感覺(jué)調(diào)用一個(gè)方法誰(shuí)不會(huì)?它到底好在哪才是最重要的,我發(fā)布的文章都秉承發(fā)現(xiàn)問(wèn)題,解決問(wèn)題的理念展開(kāi),好了,不吹了,精彩的要來(lái)了!

編程痛點(diǎn)

作為Java程序員遇到NullPointerException是非常痛苦的,這可能是我們遇到的最多的異常了

前后端聯(lián)調(diào):嗨!哥們,你這500啥意思呀?

后端:先是沉思,這怎么會(huì)有空指針?對(duì)前端說(shuō):哥們等1分鐘,馬上解決,我可不能說(shuō)空指針,我可是老開(kāi)發(fā)了!說(shuō)空指針多沒(méi)面子。

產(chǎn)生過(guò)這種無(wú)奈的請(qǐng)?jiān)谠u(píng)論區(qū)大聲說(shuō)出來(lái)!無(wú)論是新手還是專(zhuān)家,在NullPointerException面前可謂眾生平等

我們編程時(shí)經(jīng)常承受:寫(xiě)了類(lèi)型檢查,值判斷,最終沒(méi)想到竟然是一個(gè)null的痛苦,毫不留情的甩出來(lái)一個(gè)令人厭煩的NullPointerException,比如:

系統(tǒng)中用戶(hù),有些用戶(hù)進(jìn)行了實(shí)名認(rèn)證,擁有身份證信息,有些用戶(hù)并沒(méi)有完成實(shí)名認(rèn)證就沒(méi)有身份證信息【不要深究設(shè)計(jì)是否合理,僅僅是舉例講解Optional知識(shí)點(diǎn)】

用戶(hù)類(lèi):

public class User {

private Long id;

private String name;
// 身份證對(duì)象
private IdCard idCard;
// getter、setter、toString
}

身份證類(lèi):

public class IdCard {
private Long id;
// 身份證號(hào)碼
private String idNum;
// getter、setter、toString
}

測(cè)試類(lèi):獲取用戶(hù)的身份證號(hào)碼

public class OptionalMain {

public static void main(String[] args) {
// 創(chuàng)建用戶(hù)對(duì)象
User user = new User();
// 調(diào)用一系列g(shù)et方法獲取身份證號(hào)碼
// 因?yàn)檎{(diào)用 getIdCard()時(shí)并沒(méi)有身份證對(duì)象為null,再調(diào)用getIdNum方法則出現(xiàn) NullPointerException
String idNum = user.getIdCard().getIdNum();
System.out.println(idNum);
}
}

運(yùn)行結(jié)果:

如果user是傳遞進(jìn)來(lái)的,傳進(jìn)來(lái)的user也有可能是null

解決方案

怎樣做才能避免不期而至的NullPointerException?通常,在需要的地方添加null的檢查,所以我們的代碼多了很多的判斷是否為null的驗(yàn)證,影響代碼結(jié)構(gòu),甚至有時(shí)不加思索是否需要驗(yàn)證也會(huì)統(tǒng)一加上非空判斷,來(lái)避免不可預(yù)知的空值,防止生產(chǎn)環(huán)境造成損失!并且添加的方式往往各有不同:

嵌套判斷:

public class OptionalMain {
public static void main(String[] args) {
User user = new User();
// 判斷user是否為null
if(user != null) {
IdCard idCard = user.getIdCard();
// 判斷 idCard 是否為null
if(idCard != null) {
// 獲取身份證號(hào)碼
System.out.println(idCard.getIdNum());
}else {
System.out.println("未實(shí)名認(rèn)證!");
}
}else {
System.out.println("該用戶(hù)不存在!");
}
}
}

逐個(gè)判斷:

public class OptionalMain {

/**
* 獲取身份證號(hào)碼
* @param user:用戶(hù)
* @return:身份證號(hào)碼
*/
public static String getUserIdcardNum(User user) {
// 判斷用戶(hù)是否為空
if(user == null) {
return "無(wú)此用戶(hù)";
}
// 判斷是否實(shí)名認(rèn)證
if(user.getIdCard() == null) {
return "該用戶(hù)未實(shí)名認(rèn)證";
}
// 返回身份證號(hào)碼,如果:要對(duì)身份證號(hào)碼進(jìn)行操作,也要對(duì)idNum進(jìn)行非空判斷
return user.getIdCard().getIdNum();
}

public static void main(String[] args) {
// 創(chuàng)建用戶(hù)對(duì)象
User user = new User();
// 1、調(diào)用獲取身份證方法,有用戶(hù)但未實(shí)名
System.out.println("******未認(rèn)證******");
String userIdcardNum1 = getUserIdcardNum(user);
System.out.println("結(jié)果:" + userIdcardNum1);
// 2、傳遞空用戶(hù)
System.out.println("******空用戶(hù)******");
String userIdcardNum2 = getUserIdcardNum(null);
System.out.println("結(jié)果:" + userIdcardNum2);
// 3、創(chuàng)建身份證對(duì)象
IdCard idCard = new IdCard();
idCard.setId(1L);
idCard.setIdNum("411481199611111516");
user.setIdCard(idCard);
// 傳遞實(shí)名認(rèn)證的用戶(hù)
System.out.println("******已認(rèn)證******");
String userIdcardNum3 = getUserIdcardNum(user);
System.out.println("結(jié)果:" + userIdcardNum3);
}
}

運(yùn)行結(jié)果:

如果有其他要求,就要做更多的非空判斷,影響代碼的連貫性,凈判斷空值了

一旦忘記判斷某一個(gè)值是否為空,就又要和 NullPointerException 偶遇了,它并不是女朋友,而是最不想遇見(jiàn)的【債主】

null值帶來(lái)的問(wèn)題

  • NullPointerException是目前Java程序開(kāi)發(fā)中最典型的異常,有些書(shū)中稱(chēng)其為錯(cuò)誤之源,個(gè)人覺(jué)得有點(diǎn)夸張,你覺(jué)著呢?
  • 各種非空判斷,讓代碼變的冗余,閱讀性很糟糕,非空判斷對(duì)業(yè)務(wù)實(shí)現(xiàn)是毫無(wú)意義的
  • null值本身也毫無(wú)意義,可以認(rèn)為是給對(duì)象一個(gè)【錯(cuò)誤的默認(rèn)值】
  • null可以被賦值給任意的引用數(shù)據(jù)類(lèi)型,如果是分布式系統(tǒng),該值被傳遞到另一個(gè)服務(wù)中,無(wú)法知道最初的它是什么類(lèi)型,也無(wú)法對(duì)其進(jìn)行賦值
  • Java為了簡(jiǎn)化語(yǔ)言,摒棄了指針的概念,但是 NullPointerException是個(gè)例外

Optional的出現(xiàn)

Java團(tuán)隊(duì)結(jié)合Haskell和Scala語(yǔ)言對(duì)null值的處理方式,在JDK8時(shí)推出Optional類(lèi)來(lái)專(zhuān)門(mén)處理空值問(wèn)題,當(dāng)然該類(lèi)并不是為了避免我們?nèi)?xiě)!=null的非空判斷,他功能很強(qiáng),配合Lambda表達(dá)式更香

源碼注釋

/**
* A container object which may or may not contain a non-null value.
一個(gè)可以包含或不包含非空值的容器對(duì)象
* If a value is present, {@code isPresent()} will return {@code true} and
* {@code get()} will return the value.
如果存在值,isPresent()方法會(huì)返回true,通過(guò)get()方法返回值
*
*

Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(java.lang.Object) orElse()}
* (return a default value if value not present) and
* {@link #ifPresent(java.util.function.Consumer) ifPresent()} (execute a block
* of code if the value is present).
提供了取決于是否存在包含值的其他方法,比如orElse,如果值不存在,則返回默認(rèn)值 并且 可以通過(guò)ifPresent()
判斷值是否存在,存在則執(zhí)行代碼塊
*

This is a value-based
* class; use of identity-sensitive operations (including reference equality
* ({@code ==}), identity hash code, or synchronization) on instances of
* {@code Optional} may have unpredictable results and should be avoided.
這是一個(gè)基于值的類(lèi),應(yīng)避免使用于身份敏感操作【這里應(yīng)該意思是:對(duì)象是否存在不確定的敏感操作】(包括引用 ==,哈?;蛲剑┑膶?shí)例可能會(huì)產(chǎn)生不可預(yù)測(cè)的結(jié)果
* @since

從Optional類(lèi)的定義和聲明來(lái)看特點(diǎn)如下:

  • 是一個(gè)final類(lèi),不可被繼承,并且是一個(gè)泛型類(lèi)
  • 該類(lèi)是一個(gè)容器,可以用來(lái)存儲(chǔ)對(duì)象
  • 該類(lèi)提供了一系列方法來(lái)判斷是否有值【isPresent()】和獲取值【get()】

Optional解決null問(wèn)題

通過(guò)案例感受Optional處理null的套路:

  • 將可能為null,或者說(shuō)允許為null的數(shù)據(jù)存儲(chǔ)進(jìn)Optional容器中
  • 通過(guò)Optional的map、filter、flatMap方法對(duì)數(shù)據(jù)進(jìn)行處理,獲取需要的對(duì)象屬性,用法和Stream相同
  • 如果數(shù)據(jù)為空了,可以返回一個(gè)自定義對(duì)象,或者拋出異常都可以,隨你所愿

User類(lèi):

public class User {

private Long id;

private String name;

// 將可能為null的對(duì)象放入Optional中
private Optional idCard;

// getter、setter、toString
}

IdCard類(lèi):

public class IdCard {
private Long id;
// 如果身份證號(hào)碼也允許為null,也可以放入Optional中【Optional
// 但是實(shí)名認(rèn)證了,身份證號(hào)碼就是必須的了不是嗎,
// 一旦使用了Optional,沒(méi)有身份證號(hào)碼時(shí),也不會(huì)出現(xiàn)報(bào)錯(cuò),可能會(huì)出現(xiàn)數(shù)據(jù)錯(cuò)誤,所以也不要濫用
private String idNum;
// getter、setter、toString
}

測(cè)試類(lèi):

public class OptionalMain {

/**
* 獲取身份證號(hào)碼
* @param user:用戶(hù)
* @return:身份證號(hào)碼
*/
public static String getUserIdcardNum(User user){
// 將User通過(guò)Optional.of() 方法 存儲(chǔ)進(jìn)Optional
Optional optionalUser = Optional.of(user);
// 通過(guò)map方法先獲取user中身份對(duì)象,orElse:如果沒(méi)有,返回一個(gè)自定義的Optional對(duì)象
Optional optionalIdCard = optionalUser.map(User::getIdCard).orElse(Optional.of(new IdCard()));
// 通過(guò)map方法獲取IdCard中的idNum,如果沒(méi)有返回 "無(wú)實(shí)名認(rèn)證"字符串
String idNum = optionalIdCard.map(IdCard::getIdNum).orElse("無(wú)實(shí)名認(rèn)證");
return idNum;
}

public static void main(String[] args){
User user = new User();
// 將user對(duì)象傳進(jìn)方法中,該對(duì)象中的IdCard為null
System.out.println(getUserIdcardNum(user));
}
}

運(yùn)行結(jié)果:

我們僅僅傳入了user對(duì)象,IdCard為null,通過(guò)getUserIdcardNum方法處理之后,返回定義的無(wú)實(shí)名認(rèn)證,這里并沒(méi)有做if...else的判斷,這樣的代碼看起來(lái)更優(yōu)雅,不是嗎?

總結(jié)來(lái)說(shuō):

  • 把對(duì)象放進(jìn)Optional中,可以通過(guò)Optional提供的API來(lái)操作容器中的對(duì)象
  • 如:對(duì)象非空正常使用,我們可以通過(guò)get()方法獲取對(duì)象
  • 如果是空可以通過(guò)某些方法【orElse、orElseGet、orElseThrow】,返回自定義的結(jié)果,避免空指針異常出現(xiàn)
  • 通過(guò)一些判斷方法來(lái)判斷Optional中對(duì)象是否為null

接下來(lái)講解一下Optional中的API,系統(tǒng)認(rèn)識(shí),學(xué)習(xí)強(qiáng)大的Optional

Optional結(jié)構(gòu)

Optional方法概覽

方法

作用

Optional.empty()

創(chuàng)建一個(gè)空的 Optional 實(shí)例

Optional.of(T t)

創(chuàng)建一個(gè) Optional 實(shí)例,當(dāng) t為null時(shí)拋出異常

Optional.ofNullable(T t)

創(chuàng)建一個(gè) Optional 實(shí)例,但當(dāng) t為null時(shí)不會(huì)拋出異常,而是返回一個(gè)空的實(shí)例

get()

獲取optional實(shí)例中的對(duì)象,當(dāng)optional 容器為空時(shí)報(bào)錯(cuò)

isPresent()

判斷optional是否為空,如果空則返回false,否則返回true

ifPresent(Consumer c)

如果optional不為空,則將optional中的對(duì)象傳給Comsumer函數(shù)

orElse(T other)

如果optional不為空,則返回optional中的對(duì)象;如果為null,則返回 other 這個(gè)默認(rèn)值

orElseGet(Supplier other)

如果optional不為空,則返回optional中的對(duì)象;如果為null,則使用Supplier函數(shù)生成默認(rèn)值other

orElseThrow(Supplier exception)

如果optional不為空,則返回optional中的對(duì)象;如果為null,則拋出Supplier函數(shù)生成的異常

filter(Predicate p)

如果optional不為空,則執(zhí)行斷言函數(shù)p,如果p的結(jié)果為true,則返回原本的optional,否則返回空的optional

map(Function mapper)

如果optional不為空,則將optional中的對(duì)象 t 映射成另外一個(gè)對(duì)象 u,并將 u 存放到一個(gè)新的optional容器中

flatMap(Function< T,Optional> mapper)

跟上面一樣,在optional不為空的情況下,將對(duì)象t映射成另外一個(gè)optional,區(qū)別在于:map會(huì)自動(dòng)將u放到optional中,而flatMap則需要手動(dòng)給u創(chuàng)建一個(gè)optional

強(qiáng)烈建議:打開(kāi)編輯器,多翻閱源碼,對(duì)學(xué)習(xí)和編碼都有很大幫助,剛開(kāi)始看不懂沒(méi)關(guān)系,量變產(chǎn)生質(zhì)變

Optional 創(chuàng)建

通過(guò)Optional源碼發(fā)現(xiàn):

  • 該類(lèi)final修飾,不能被繼承,只有一個(gè)Object父類(lèi)
  • 是一個(gè)泛型類(lèi),使用時(shí)為了類(lèi)型安全指明泛型類(lèi)型
  • 連個(gè)私有常量,供內(nèi)部調(diào)用,其中value為Optional容器中存儲(chǔ)的對(duì)象
  • 兩個(gè)構(gòu)造方法,無(wú)參和有參的都為私有,說(shuō)明不能通過(guò)構(gòu)造方法創(chuàng)建Optional對(duì)象,需要通過(guò)內(nèi)部提供的【empty()、of(T t)、ofNullable(T t)】三個(gè)靜態(tài)方法創(chuàng)建,這種創(chuàng)建方式其實(shí)就是【工廠模式】

代碼實(shí)現(xiàn):

// 創(chuàng)建一個(gè)包裝對(duì)象值為空的Optional對(duì)象
Optional optional1 = Optional.empty();

// 創(chuàng)建包裝對(duì)象值非空的Optional對(duì)象,如果傳入null則出現(xiàn)`NullPointerException`
Optional optional2 = Optional.of("optional");

// 創(chuàng)建包裝對(duì)象值允許為空的Optional對(duì)象
Optional optional3 = Optional.ofNullable(null);

Optional其他API

get()

作用:獲取optional實(shí)例中的對(duì)象,當(dāng)optional 容器為空時(shí)報(bào)錯(cuò)

源碼:

  • 判斷value是否為null
  • 為null,拋出 NoSuchElementException("No value present")異常
  • 不為null,返回value

null值Optional:

// 創(chuàng)建值為null的Optional對(duì)象
Optional optional = Optional.empty();
// get返回 NoSuchElementException("No value present")
String result = optional.get();
System.out.println(result);

非null值Optional:

// 創(chuàng)建值為:optional的Optional對(duì)象
Optional optional = Optional.of("optional");
// 返回值 optional
String result = optional.get();
System.out.println(result);

isPresent()

作用:判斷optional是否為空,如果空則返回false,否則返回true

源碼:

代碼實(shí)現(xiàn):

List users = new ArrayList<>();
users.add("柯南");
users.add("佩奇");
users.add("喜洋洋");
Optional> optional = Optional.of(users);
// 判斷并消費(fèi)
optional.ifPresent(System.out::println);

orElse(T other)

作用:如果optional不為空,則返回optional中的對(duì)象;如果為null,則返回 other 這個(gè)默認(rèn)值

源碼:

代碼實(shí)現(xiàn):

User user = new User(1L,"格雷福斯");
// 1、存儲(chǔ)非null數(shù)據(jù)
Optional userOptional = Optional.ofNullable(user);
// 獲取用戶(hù)名
String name1 = userOptional.orElse(new User(0L, "帥氣添甄")).getName();
// 非null,結(jié)果為:格雷福斯
System.out.println(name1);

// 2、存儲(chǔ)null數(shù)據(jù)
Optional nullOptional = Optional.ofNullable(null);
String name2 = nullOptional.orElse(new User(0L, "帥氣添甄")).getName();
// 為null,結(jié)果:帥氣添甄
System.out.println(name2);

orElseGet(Supplierother)

作用:如果optional不為空,則返回optional中的對(duì)象;如果為null,則使用Supplier函數(shù)生成默認(rèn)值other

源碼:

代碼實(shí)現(xiàn):

User user = new User(1L,"格雷福斯");
Optional userOptional = Optional.ofNullable(user);
// 為null直接返回`Supplier`生產(chǎn)型函數(shù)接口返回的對(duì)象
String name = userOptional.orElseGet(() new User(0L, "添甄")).getName();
System.out.println(name);

orElseThrow(Supplierexception)

作用:如果optional不為空,則返回optional中的對(duì)象;如果為null,則拋出Supplier函數(shù)生成的異常

源碼:

代碼實(shí)現(xiàn):

User user = new User(1L,"格雷福斯");
Optional userOptional = Optional.ofNullable(user);
// 為null直接返回`Supplier`生產(chǎn)型函數(shù)接口返回的對(duì)象
String name = userOptional.orElseGet(() new User(0L, "添甄")).getName();
System.out.println(name);

orElseThrow(Supplierexception)

作用:如果optional不為空,則返回optional中的對(duì)象;如果為null,則拋出Supplier函數(shù)生成的異常

源碼:

代碼實(shí)現(xiàn):

User user = new User(1L,"格雷福斯");
Optional userOptional = Optional.ofNullable(user);
// 如果數(shù)據(jù)為null,拋出 指定異常
String name = userOptional.orElseThrow(() new RuntimeException("無(wú)數(shù)據(jù)")).getName();
System.out.println(name);

filter(Predicatep)

作用:如果optional不為空,則執(zhí)行斷言函數(shù)p,如果p的結(jié)果為true,則返回原本的optional,否則返回空的optional

源碼:

代碼實(shí)現(xiàn):

User user = new User(1L,"格雷福斯");
Optional userOptional = Optional.ofNullable(user);

// 過(guò)濾名字長(zhǎng)度大于3,如果有值才輸出,沒(méi)值就不輸出
userOptional.filter(item -> item.getName().length() > 3).ifPresent(System.out::println);

map(Function mapper)

作用:如果optional不為空,則將optional中的對(duì)象 t 映射成另外一個(gè)對(duì)象 u,并將 u 存放到一個(gè)新的optional容器中,該方法與Stream的map作用一樣

源碼:

代碼實(shí)現(xiàn):

User user = new User(1L,"格雷福斯");
Optional userOptional = Optional.ofNullable(user);

// 只獲取用戶(hù)名
String name = userOptional.map(User::getName).orElse("添甄");
System.out.println(name);

flatMap(Function< T,Optional> mapper)

作用:在optional不為空的情況下,將對(duì)象t映射成另外一個(gè)optional,17-flatMapmap接收的是U類(lèi)型,而flatMap接收的是Optional類(lèi)型,返回也是需要放進(jìn)Optional中

源碼:

代碼實(shí)現(xiàn):

User user = new User(1L,"格雷福斯");
Optional userOptional = Optional.ofNullable(null);
Optional optional = userOptional.flatMap(item -> Optional.ofNullable(item.getName()));
String name = optional.orElse("添甄");
System.out.println(name);

錯(cuò)誤示范

獲取用戶(hù)名:

User user = new User(1L,"格雷福斯");
Optional userOptional = Optional.ofNullable(user);
// 判斷是否有值
if (userOptional.isPresent()) {
String name = userOptional.get().getName();
System.out.println(name);
}else {
System.out.println("無(wú)值");
}

通過(guò)調(diào)用isPresent方法判斷是否有值,這還是增加了判斷,破壞代碼結(jié)構(gòu)

正確姿勢(shì):

多用map,orElse,filter方法發(fā)揮Optional的作用

User user = new User(1L,"格雷福斯");
Optional userOptional = Optional.ofNullable(user);
String name = userOptional.map(User::getName).orElse("無(wú)值");
System.out.println(name);

總結(jié)

  • Optional是一個(gè)用來(lái)解決null值,避免發(fā)生空指針異常的容器,配合Lambda表達(dá)式寫(xiě)出優(yōu)雅代碼
  • 靜態(tài)工廠方法Optional.empty()、Optional.of()以及Optional.ofNullable()創(chuàng)建Optional對(duì)象
  • Optional類(lèi)包含多種方法,其中map、flatMap、filter,它們?cè)诟拍钌吓cStream類(lèi)中對(duì)應(yīng)的方法十分相似
  • 使用Optional能幫助你開(kāi)發(fā)出更便于閱讀和簡(jiǎn)介的程序
  • 多使用Optional中的方法給定默認(rèn)值,比如map、orElse等方法來(lái)避免過(guò)多的if判斷

文章出自:??石添的編程哲學(xué)??,如有轉(zhuǎn)載本文請(qǐng)聯(lián)系【石添的編程哲學(xué)】今日頭條號(hào)。


網(wǎng)站欄目:正確使用Java8中的Optional,它遠(yuǎn)比我們想象的優(yōu)秀
文章路徑:http://www.dlmjj.cn/article/cocoioj.html