日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

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

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Java中NullPointerException的完美解決方案

null在Java中帶來(lái)的麻煩

我相信所有的Java程序猿一定都遇到過(guò) NullPointerException ,空指針在Java程序中是最常見(jiàn)的,也是最煩人的;它讓我們很多程序猿產(chǎn)生了根深蒂固的感覺(jué),所有可能產(chǎn)生空指針的地方都得加上 if-else 檢查,但是這帶給我們很多麻煩。

成都創(chuàng)新互聯(lián)是一家專(zhuān)業(yè)提供肇州企業(yè)網(wǎng)站建設(shè),專(zhuān)注與成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、H5開(kāi)發(fā)、小程序制作等業(yè)務(wù)。10年已為肇州眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專(zhuān)業(yè)網(wǎng)絡(luò)公司優(yōu)惠進(jìn)行中。

  • Java本身是強(qiáng)類(lèi)型的,但是null破壞了這個(gè)規(guī)則,它可以被賦值給任何對(duì)象

  • Java的設(shè)計(jì)是讓程序猿對(duì)指針無(wú)感知,但是null指針是個(gè)例外

  • 它會(huì)是代碼變得很臃腫,到處都充斥著 if-else 的空檢查,甚至是多層嵌套,代碼可讀性下降
  • null本身毫無(wú)意義,表示不了 無(wú)

前兩點(diǎn)不需要特別的說(shuō)明,后兩點(diǎn)舉個(gè)例子來(lái)說(shuō)明一下:假如一個(gè)人擁有一個(gè)手機(jī),每個(gè)手機(jī)都有生成廠(chǎng)商,每個(gè)廠(chǎng)商都會(huì)有個(gè)名字,用類(lèi)表示的話(huà):

 
 
 
 
  1. public class Person { 
  2.     private Phone phone; 
  3.  
  4.     public Phone getPhone() { 
  5.         return phone; 
  6.     } 
  7.  
  8. public class Phone { 
  9.     private Producer producer; 
  10.  
  11.     public Producer getProducer() { 
  12.         return producer; 
  13.     } 
  14.  
  15. public class Producer { 
  16.     private String name; 
  17.  
  18.     public String getName() { 
  19.         return name; 
  20.     } 

在這個(gè)例子中,假如我們需要取到手機(jī)生成廠(chǎng)商的名字

 
 
 
 
  1. public String getPhoneProducerName(Person person) { 
  2.     return person.getPhone().getProducer().getName(); 

由于不一定每個(gè)人都會(huì)有一個(gè)手機(jī),所有在調(diào)用 getProducer() 時(shí)可能會(huì)出現(xiàn) NullPointerException 。

一門(mén)設(shè)計(jì)語(yǔ)言本來(lái)就是來(lái)描述世界的,在這個(gè)事例中有的人有手機(jī),有的人也可能沒(méi)有手機(jī),所以在調(diào)用 person.getPhone() 返回的值就應(yīng)該包含有和無(wú)這兩種情況,現(xiàn)在通過(guò)返回 null 來(lái)表示無(wú),但是在調(diào)用 getProducer() 卻又會(huì)拋出異常,這樣就不太符合現(xiàn)實(shí)邏輯;所以把 null 來(lái)用來(lái)表示 無(wú) 不合適

在遇到這種情況通常的做法是做null檢查,甚至是每個(gè)地方可能發(fā)生null指針的做檢查。

 
 
 
 
  1. public String getPhoneProducerName(Person person) { 
  2.     if (person.getPhone() == null) { 
  3.         return "無(wú)名字"; 
  4.     } 
  5.     if (person.getPhone().getProducer() == null) { 
  6.         return "無(wú)名字"; 
  7.     } 
  8.     return person.getPhone().getProducer().getName(); 

這里我已經(jīng)試圖在減少代碼的層級(jí),如果使用的是 if-else ,代碼的層級(jí)會(huì)更深,代碼可讀性下降。

Optional的簡(jiǎn)單介紹

吐槽了那么多現(xiàn)狀的不好,現(xiàn)在可以祭出我們的解決方案了 Optional ;千呼萬(wàn)喚始出來(lái),猶抱琵琶半遮面;那 Optional 到底是個(gè)什么東西,我們一起來(lái)逐步解開(kāi)它的面紗。

Optional 本身只是對(duì)對(duì)象的簡(jiǎn)單包裝,如果對(duì)象為空,那么會(huì)構(gòu)建一個(gè)空的 Optional ;這樣一來(lái) Optional 就包含了存在和不存在兩個(gè)情況, 接下來(lái)可以看下上面的例子改過(guò)之后

 
 
 
 
  1. public class Person { 
  2.     private Optional phone; 
  3.  
  4.     public Optional getPhone() { 
  5.         return phone; 
  6.     } 
  7.  
  8. public class Phone { 
  9.     private Producer producer; 
  10.  
  11.     public Producer getProducer() { 
  12.         return producer; 
  13.     } 
  14.  
  15. public class Producer { 
  16.     private String name; 
  17.  
  18.     public String getName() { 
  19.         return name; 
  20.     } 

由于有的人可能沒(méi)有手機(jī),有的人有,所以 Phone 需要用 Optional 包裝起來(lái);手機(jī)本身一定會(huì)有生產(chǎn)的廠(chǎng)商,廠(chǎng)商一定會(huì)有一個(gè)名字,所以這兩個(gè)不需要用 Optional 包裝起來(lái)。這里我們會(huì)發(fā)現(xiàn)使用了 Optional 會(huì)豐富代碼的語(yǔ)義,讓代碼更加符合現(xiàn)實(shí)。

而當(dāng)我們?cè)谡{(diào)用 phone.getProducer().getName() 的時(shí)候不需要做null指針的檢查,如果說(shuō)在這里發(fā)生了 NullPointerException ,說(shuō)明這里數(shù)據(jù)本身是有問(wèn)題的,不符合現(xiàn)實(shí),就應(yīng)該讓問(wèn)題暴露出來(lái),而不是像上面的代碼一樣把問(wèn)題掩蓋。

Optional的常用方法使用

1. Optional的創(chuàng)建方法

 
 
 
 
  1. Optional empty = Optional.empty();  //申明一個(gè)空的Optional 
  2. Optional person = Optional.of(new Person()); //包裝Person 
  3. Optional person2 = Optional.of(null); //不允許的操作,傳入null 會(huì)拋出空指針異常 
  4. Optional optionalPerson = Optional.ofNullable(null); //允許傳null, 返回一個(gè)空的Optional 

2. Optional值的獲取方式

  • map、flatMap 首先我們重新定義一下Phone類(lèi),除了有生產(chǎn)廠(chǎng)商之外,還有個(gè)型號(hào);
 
 
 
 
  1. public class Phone { 
  2.     private String model; 
  3.     private Producer producer; 
  4.  
  5.     public Producer getProducer() { 
  6.         return producer; 
  7.     } 
  8.     public String getModel() { 
  9.         return model; 
  10.     } 

當(dāng)我們需要獲取到手機(jī)的型號(hào)的時(shí)候可以這樣:

 
 
 
 
  1. Optional optionalPhone = Optional.of(new Phone()); 
  2. Optional model = optionalPhone.map(Phone::getModel); 

當(dāng)我們需要通過(guò)Person對(duì)象獲取到Phone的型號(hào),會(huì)想到這樣:

 
 
 
 
  1. Optional optionalPerson = Optional.of(new Person()); 
  2. optionalPerson.map(Person::getPhone).map(Phone::getModel); 

當(dāng)我們寫(xiě)出來(lái)的時(shí)候發(fā)現(xiàn)編譯器不能通過(guò)。是因?yàn)?nbsp;Person::getPhone 返回的是一個(gè) Optional ,調(diào)用 optionalPerson.map(Person::getPhone) 返回的就是 Optional> ,所以再 .map 的就無(wú)法拿到手機(jī)型號(hào),那如何能夠讓返回的結(jié)果不是 Optional> ,而是 Optional 呢?

這里需要用到另一個(gè)方法 flatMap 。 flatMap 和 map 的區(qū)別,我在剛開(kāi)始學(xué)習(xí)的時(shí)候,看到了網(wǎng)上的各種解釋都很繞,看的很暈,最后直接打開(kāi)源碼來(lái)看,發(fā)現(xiàn)實(shí)現(xiàn)很簡(jiǎn)單,很容易理解,來(lái)看下源碼:

 
 
 
 
  1. public Optional map(Function mapper) { 
  2.     Objects.requireNonNull(mapper); 
  3.     if (!isPresent()) 
  4.         return empty(); 
  5.     else { 
  6.         return Optional.ofNullable(mapper.apply(value)); 
  7.     } 
  8. public Optional flatMap(Function> mapper) { 
  9.     Objects.requireNonNull(mapper); 
  10.     if (!isPresent()) 
  11.         return empty(); 
  12.     else { 
  13.         return Objects.requireNonNull(mapper.apply(value)); 
  14.     } 

map 方法在返回的時(shí)候會(huì)包裝一層 Optional ; flatMap 在返回的時(shí)候直接把函數(shù)的返回值返回了,函數(shù)的結(jié)果必須是 Optional ;那么在前面的例子中我們直接調(diào)用 flatMap 返回的結(jié)果就是 Optional

 
 
 
 
  1. Optional optionalPerson = Optional.of(new Person()); 
  2. optionalPerson.flatMap(Person::getPhone).map(Phone::getModel); 
  • 取出 Optional 中的值對(duì)象:get、orElse、orElseGet、orElseThrow、ifPresent
  1. get() : 當(dāng)你明確知道Optional中有值的話(huà)可以直接調(diào)用該方法,當(dāng)Optional中沒(méi)有值是該方法會(huì)拋出異常 NoSuchElementException ;所以當(dāng)如果存在空值的話(huà)建議就不要調(diào)用該方法,因?yàn)檫@樣和做null檢查就沒(méi)有區(qū)別了
  2. orElse(T other) : 提供一個(gè)默認(rèn)值,當(dāng)值不存在是返回這個(gè)默認(rèn)值

  3. orElseGet(Supplier other) : 當(dāng)值不存在的時(shí)候會(huì)調(diào)用supper函數(shù),如果說(shuō)返回這個(gè)默認(rèn)值的邏輯較多,那么調(diào)用這個(gè)方法比較合適;

  4. orElseThrow(Supplier exceptionSupplier) : 當(dāng)值為空時(shí)會(huì)拋出一個(gè)自定義的異常

  5. ifPresent(Consumer consumer) : 當(dāng)值不為空是會(huì)調(diào)用 consumer 函數(shù),如果值為空,那么這個(gè)方法什么都不做
  • filter 過(guò)濾出滿(mǎn)足條件的對(duì)象 假如我們需要過(guò)濾出手機(jī)型號(hào) IOS 的手機(jī),并打印出型號(hào),代碼如下:
 
 
 
 
  1. Person person = new Person(Optional.of(new Phone("IOS"))); 
  2.         Optional optionalPerson = Optional.of(person); 
  3.         optionalPerson.flatMap(Person::getPhone) 
  4.                 .filter(phone -> "IOS".equals(phone.getModel())) 
  5.                 .map(Phone::getModel) 
  6.                 .ifPresent(System.out::println); 
  1. 我們討論了null在Java程序的問(wèn)題

  2. 介紹Java8中引入了 Optional 來(lái)表示有和無(wú)的情況以及初始化的方式
  3. 舉例說(shuō)明了 Optional 中經(jīng)常使用到的方法

分享題目:Java中NullPointerException的完美解決方案
當(dāng)前路徑:http://m.5511xx.com/article/cdidscc.html