自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

談?wù)勗贘ava中如何優(yōu)雅地判空 !

開(kāi)發(fā) 后端
作為搬磚黨的一族們,我們對(duì)判空一定再熟悉不過(guò)了,不要跟我說(shuō)你很少進(jìn)行判空,除非你喜歡NullPointerException。

 判空災(zāi)難

作為搬磚黨的一族們,我們對(duì)判空一定再熟悉不過(guò)了,不要跟我說(shuō)你很少進(jìn)行判空,除非你喜歡NullPointerException。

不過(guò)NullPointerException對(duì)于很多猿們來(lái)說(shuō),也是Exception家族中最親近的一員了。

[[343874]]

為了避免NullPointerException來(lái)找我們,我們經(jīng)常會(huì)進(jìn)行如下操作。 

  1. if (data != null) {  
  2.     do sth.  

如果一個(gè)類(lèi)中多次使用某個(gè)對(duì)象,那你可能要一頓操作,so:

“世界第九大奇跡”就這樣誕生了。Maybe你會(huì)想,項(xiàng)目中肯定不止你一個(gè)人會(huì)這樣一頓操作,然后按下Command+Shift+F,真相就在眼前:

What,我們有接近一萬(wàn)行的代碼都是在判空?

好了,接下來(lái),要進(jìn)入正題了。

NullObject模式

對(duì)于項(xiàng)目中無(wú)數(shù)次的判空,對(duì)代碼質(zhì)量整潔度產(chǎn)生了十分之惡劣的影響,對(duì)于這種現(xiàn)象,我們稱(chēng)之為“判空災(zāi)難”。

那么,這種現(xiàn)象如何治理呢,你可能聽(tīng)說(shuō)過(guò)NullObject模式,不過(guò)這不是我們今天的武器,但是還是需要介紹一下NullObject模式。

什么是NullObject模式呢?

In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral ("null") behavior. The null object design pattern describes the uses of such objects and their behavior (or lack thereof).

以上解析來(lái)自Wikipedia。

NullObject模式首次發(fā)表在“ 程序設(shè)計(jì)模式語(yǔ)言 ”系列叢書(shū)中。一般的,在面向?qū)ο笳Z(yǔ)言中,對(duì)對(duì)象的調(diào)用前需要使用判空檢查,來(lái)判斷這些對(duì)象是否為空,因?yàn)樵诳找蒙蠠o(wú)法調(diào)用所需方法。

空對(duì)象模式的一種典型實(shí)現(xiàn)方式如下圖所示(圖片來(lái)自網(wǎng)絡(luò)):

示例代碼如下(命名來(lái)自網(wǎng)絡(luò),哈哈到底是有多懶):

Nullable是空對(duì)象的相關(guān)操作接口,用于確定對(duì)象是否為空,因?yàn)樵诳諏?duì)象模式中,對(duì)象為空會(huì)被包裝成一個(gè)Object,成為Null Object,該對(duì)象會(huì)對(duì)原有對(duì)象的所有方法進(jìn)行空實(shí)現(xiàn)… 

  1. public interface Nullable {  
  2.     boolean isNull();  

這個(gè)接口定義了業(yè)務(wù)對(duì)象的行為。 

  1. public interface DependencyBase extends Nullable {  
  2.     void Operation();  

這是該對(duì)象的真實(shí)類(lèi),實(shí)現(xiàn)了業(yè)務(wù)行為接口DependencyBase與空對(duì)象操作接口Nullable。 

  1. public class Dependency implements DependencyBase, Nullable {  
  2.     @Override  
  3.     public void Operation() {  
  4.         System.out.print("Test!");  
  5.     }  
  6.     @Override  
  7.     public boolean isNull() {  
  8.         return false;  
  9.     }  

這是空對(duì)象,對(duì)原有對(duì)象的行為進(jìn)行了空實(shí)現(xiàn)。 

  1. public class NullObject implements DependencyBase{  
  2.     @Override  
  3.     public void Operation() {  
  4.         // do nothing  
  5.     }  
  6.     @Override  
  7.     public boolean isNull() {  
  8.         return true;  
  9.     }  

在使用時(shí),可以通過(guò)工廠調(diào)用方式來(lái)進(jìn)行空對(duì)象的調(diào)用,也可以通過(guò)其他如反射的方式對(duì)對(duì)象進(jìn)行調(diào)用(一般多耗時(shí)幾毫秒)在此不進(jìn)行詳細(xì)敘述。 

  1. public class Factory {  
  2.     public static DependencyBase get(Nullable dependencyBase){  
  3.         if (dependencyBase == null){  
  4.             return new NullObject(); 
  5.          }  
  6.         return new Dependency();  
  7.     } 
  8.  

這是一個(gè)使用范例,通過(guò)這種模式,我們不再需要進(jìn)行對(duì)象的判空操作,而是可以直接使用對(duì)象,也不必?fù)?dān)心NPE(NullPointerException)的問(wèn)題。 

  1. public class Client {  
  2.     public void test(DependencyBase dependencyBase){  
  3.         Factory.get(dependencyBase).Operation(); 
  4.     }  

關(guān)于空對(duì)象模式,更具體的內(nèi)容大家也可以多找一找資料,上述只是對(duì)NullObject的簡(jiǎn)單介紹,但是,今天我要推薦的是一款協(xié)助判空的插件NR Null Object,讓我們來(lái)優(yōu)雅地進(jìn)行判空,不再進(jìn)行一頓操作來(lái)定義繁瑣的空對(duì)象接口與空獨(dú)享實(shí)現(xiàn)類(lèi)。

.NR Null Object

NR Null Object是一款適用于Android Studio、IntelliJ IDEA、PhpStorm、WebStorm、PyCharm、RubyMine、AppCode、CLion、GoLand、DataGrip等IDEA的Intellij插件。其可以根據(jù)現(xiàn)有對(duì)象,便捷快速生成其空對(duì)象模式需要的組成成分,其包含功能如下:

  1.  分析所選類(lèi)可聲明為接口的方法;
  2.  抽象出公有接口;
  3.  創(chuàng)建空對(duì)象,自動(dòng)實(shí)現(xiàn)公有接口;
  4.  對(duì)部分函數(shù)進(jìn)行可為空聲明;
  5.  可追加函數(shù)進(jìn)行再次生成;
  6.  自動(dòng)的函數(shù)命名規(guī)范

讓我們來(lái)看一個(gè)使用范例:

怎么樣,看起來(lái)是不是非??焖俦憬荩恍枰谠行枰M(jìn)行多次判空的對(duì)象中,郵件彈出菜單,選擇Generate,并選擇NR Null Object即可自動(dòng)生成相應(yīng)的空對(duì)象組件。

那么如何來(lái)獲得這款插件呢?

安裝方式

可以直接通過(guò)IDEA的Preferences中的Plugins倉(cāng)庫(kù)進(jìn)行安裝。

選擇 Preferences → Plugins → Browse repositories   

搜索“NR Null Oject”或者“Null Oject”進(jìn)行模糊查詢(xún),點(diǎn)擊右側(cè)的Install,restart IDEA即可。

Optional

還有一種方式是使用Java8特性中的Optional來(lái)進(jìn)行優(yōu)雅地判空,Optional來(lái)自官方的介紹如下:

A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.

一個(gè)可能包含也可能不包含非null值的容器對(duì)象。如果存在值,isPresent()將返回true,get()將返回該值。

話(huà)不多說(shuō),舉個(gè)例子。

[[343876]]

有如下代碼,需要獲得Test2中的Info信息,但是參數(shù)為T(mén)est4,我們要一層層的申請(qǐng),每一層都獲得的對(duì)象都可能是空,最后的代碼看起來(lái)就像這樣。 

  1. public String testSimple(Test4 test) { 
  2.        if (test == null) {  
  3.           return "";  
  4.       }  
  5.       if (test.getTest3() == null) {  
  6.           return "";  
  7.       }  
  8.       if (test.getTest3().getTest2() == null) {  
  9.           return "";  
  10.       }  
  11.       if (test.getTest3().getTest2().getInfo() == null) {  
  12.           return "";  
  13.       }  
  14.       return test.getTest3().getTest2().getInfo(); 
  15.    } 

但是使用Optional后,整個(gè)就都不一樣了。   

  1. public String testOptional(Test test) {  
  2.        return Optional.ofNullable(test).flatMap(Test::getTest3)  
  3.                .flatMap(Test3::getTest2)  
  4.                .map(Test2::getInfo)  
  5.                .orElse("");  
  6.    } 

1、Optional.ofNullable(test),如果test為空,則返回一個(gè)單例空Optional對(duì)象,如果非空則返回一個(gè)Optional包裝對(duì)象,Optional將test包裝; 

  1. public static <T> Optional<T> ofNullable(T value) {  
  2.      return value == null ? empty() : of(value);  
  3.  } 

2、flatMap(Test::getTest3)判斷test是否為空,如果為空,繼續(xù)返回第一步中的單例Optional對(duì)象,否則調(diào)用Test的getTest3方法; 

  1. public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {  
  2.       Objects.requireNonNull(mapper);  
  3.       if (!isPresent())  
  4.           return empty();  
  5.       else {  
  6.           return Objects.requireNonNull(mapper.apply(value));  
  7.       }  
  8.   } 

3、flatMap(Test3::getTest2)同上調(diào)用Test3的getTest2方法;

4、map(Test2::getInfo)同flatMap類(lèi)似,但是flatMap要求Test3::getTest2返回值為Optional類(lèi)型,而map不需要,flatMap不會(huì)多層包裝,map返回會(huì)再次包裝Optional; 

  1. public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {  
  2.      Objects.requireNonNull(mapper);  
  3.      if (!isPresent()) 
  4.           return empty();  
  5.      else {  
  6.          return Optional.ofNullable(mapper.apply(value));  
  7.      }  
  8.  } 

5、orElse("");獲得map中的value,不為空則直接返回value,為空則返回傳入的參數(shù)作為默認(rèn)值。 

  1. public T orElse(T other) {  
  2.     return value != null ? value : other;  

怎么樣,使用Optional后我們的代碼是不是瞬間變得非常整潔,或許看到這段代碼你會(huì)有很多疑問(wèn),針對(duì)復(fù)雜的一長(zhǎng)串判空,Optional有它的優(yōu)勢(shì),但是對(duì)于簡(jiǎn)單的判空使用Optional也會(huì)增加代碼的閱讀成本、編碼量以及團(tuán)隊(duì)新成員的學(xué)習(xí)成本。畢竟Optional在現(xiàn)在還并沒(méi)有像RxJava那樣流行,它還擁有一定的局限性。

如果直接使用Java8中的Optional,需要保證安卓API級(jí)別在24及以上。

你也可以直接引入Google的Guava。(啥是Guava?來(lái)自官方的提示)

Guava is a set of core libraries that includes new collection types (such as multimap and multiset), immutable collections, a graph library, functional types, an in-memory cache, and APIs/utilities for concurrency, I/O, hashing, primitives, reflection, string processing, and much more!

引用方式,就像這樣:   

  1. dependencies {  
  2.      compile 'com.google.guava:guava:27.0-jre'  
  3.      // or, for Android:  
  4.      api 'com.google.guava:guava:27.0-android'  
  5.    } 

不過(guò)IDEA默認(rèn)會(huì)顯示黃色,提示讓你將Guava表達(dá)式遷移到Java Api上。

當(dāng)然,你也可以通過(guò)在Preferences搜索"Guava"來(lái)Kill掉這個(gè)Yellow的提示。

關(guān)于Optional使用還有很多技巧,感興趣可以查閱Guava和Java8相關(guān)書(shū)籍和文檔。

使用Optional具有如下優(yōu)點(diǎn):

  •  將防御式編程代碼完美包裝
  •  鏈?zhǔn)秸{(diào)用
  •  有效避免程序代碼中的空指針

但是也同樣具有一些缺點(diǎn):

  1.  流行性不是非常理想,團(tuán)隊(duì)新成員需要學(xué)習(xí)成本
  2.  安卓中需要引入Guava,需要團(tuán)隊(duì)每個(gè)人處理IDEA默認(rèn)提示,或者忍受黃色提示

有時(shí)候代碼閱讀看起來(lái)可能會(huì)如下圖所示:

[[343877]]

Kotlin

當(dāng)然,Kotlin以具有優(yōu)秀的空安全性為一大特色,并可以與Java很好的混合使用,like this:

  1. test1?.test2?.test3?.test4 

如果你已經(jīng)開(kāi)始使用了Kotlin,可以不用再寫(xiě)繚亂的防御判空語(yǔ)句。如果你還沒(méi)有使用Kotlin,并不推薦為了判空優(yōu)雅而直接轉(zhuǎn)向Kotlin。 

 

責(zé)任編輯:龐桂玉 來(lái)源: java版web項(xiàng)目
相關(guān)推薦

2020-04-10 10:22:12

Java判空編程語(yǔ)言

2017-04-12 11:16:08

Python終端編程

2023-05-12 14:14:00

Java線(xiàn)程中斷

2021-03-24 10:20:50

Fonts前端代碼

2024-10-15 15:58:11

2021-04-15 00:16:18

JavaString字符串

2020-12-08 08:08:51

Java接口數(shù)據(jù)

2024-11-13 16:37:00

Java線(xiàn)程池

2024-07-10 19:06:09

2020-04-03 13:45:16

刪除Linux垃圾文件

2020-02-05 14:05:21

Java技術(shù)數(shù)組

2020-02-24 11:12:01

Linux電腦數(shù)據(jù)

2023-12-20 13:50:00

SpringBootJSON序列化

2024-11-21 09:00:00

Python字典代碼

2025-03-06 08:21:02

判空entity對(duì)象

2020-03-26 11:04:00

Linux命令光標(biāo)

2021-01-18 13:17:04

鴻蒙HarmonyOSAPP

2021-05-12 22:07:43

并發(fā)編排任務(wù)

2022-05-13 21:20:23

組件庫(kù)樣式選擇器

2021-01-28 14:53:19

PHP編碼開(kāi)發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)