為什麼牛逼的程式設計師都不用「! = null " 做判空?

2020-10-14 程式設計師麥冬

問題

為了避免空指針調用,我們經常會看到這樣的語句

...if (someobject != null) { someobject.doCalc();}...

最終,項目中會存在大量判空代碼,多麼醜陋繁冗!如何避免這種情況?我們是否濫用了判空呢?

精華回答

這是初、中級程序猿經常會遇到的問題。他們總喜歡在方法中返回null,因此,在調用這些方法時,也不得不去判空。另外,也許受此習慣影響,他們總潛意識地認為,所有的返回都是不可信任的,為了保護自己程序,就加了大量的判空。

吐槽完畢,回到這個題目本身:

進行判空前,請區分以下兩種情況:

1、null 是一個有效有意義的返回值(Where null is a valid response in terms of the contract; and)

2、null是無效有誤的(Where it isn't a valid response.)

你可能還不明白這兩句話的意思,不急,繼續往下看,接下來將詳細討論這兩種情況

先說第2種情況

null就是一個不合理的參數,就應該明確地中斷程序,往外拋錯誤。這種情況常見於api方法。例如你開發了一個接口,id是一個必選的參數,如果調用方沒傳這個參數給你,當然不行。你要感知到這個情況,告訴調用方「嘿,哥們,你傳個null給我做甚"。

相對於判空語句,更好的檢查方式有兩個

(1)assert語句,你可以把錯誤原因放到assert的參數中,這樣不僅能保護你的程序不往下走,而且還能把錯誤原因返回給調用方,豈不是一舉兩得。(原文介紹了assert的使用,這裡省略)

(2)也可以直接拋出空指針異常。上面說了,此時null是個不合理的參數,有問題就是有問題,就應該大大方方往外拋。

第1種情況會更複雜一些

這種情況下,null是個」看上去「合理的值,例如,我查詢資料庫,某個查詢條件下,就是沒有對應值,此時null算是表達了「空」的概念。

這裡給一些實踐建議:

1、假如方法的返回類型是collections,當返回結果是空時,你可以返回一個空的collections(empty list),而不要返回null,這樣調用側就能大膽地處理這個返回,例如調用側拿到返回後,可以直接print list.size(),又無需擔心空指針問題。(什麼?想調用這個方法時,不記得之前實現該方法有沒按照這個原則?所以說,代碼習慣很重要!如果你養成習慣,都是這樣寫代碼(返回空collections而不返回null),你調用自己寫的方法時,就能大膽地忽略判空)

2、返回類型不是collections,又怎麼辦呢?

那就返回一個空對象(而非null對象),下面舉個「慄子」,假設有如下代碼

public interface Action { void doSomething();} public interface Parser { Action findAction(String userInput);}

其中,Parse有一個接口FindAction,這個接口會依據用戶的輸入,找到並執行對應的動作。假如用戶輸入不對,可能就找不到對應的動作(Action),因此findAction就會返回null,接下來action調用doSomething方法時,就會出現空指針。

解決這個問題的一個方式,就是使用Null Object pattern(空對象模式)

我們來改造一下

類定義如下,這樣定義findAction方法後,確保無論用戶輸入什麼,都不會返回null對象

public class MyParser implements Parser { private static Action DO_NOTHING = new Action() { public void doSomething() { /* do nothing */ } }; public Action findAction(String userInput) { // ... if ( /* we can't find any actions */ ) { return DO_NOTHING; } }}

對比下面兩份調用實例

1、冗餘:每獲取一個對象,就判一次空

Parser parser = ParserFactory.getParser();if (parser == null) { // now what? // this would be an example of where null isn't (or shouldn't be) a valid response}Action action = parser.findAction(someInput);if (action == null) { // do nothing} else { action.doSomething();}

2、精簡

ParserFactory.getParser().findAction(someInput).doSomething();

因為無論什麼情況,都不會返回空對象,因此通過findAction拿到action後,可以放心地調用action的方法。

其他回答精選:

1、如果要用equal方法,請用object<不可能為空>.equal(object<可能為空>))

例如使用 :

"bar".equals(foo)

而不是

foo.equals("bar")

2、Java8或者guava lib中,提供了Optional類,這是一個元素容器,通過它來封裝對象,可以減少判空。不過代碼量還是不少。不爽。

3、如果你想返回null,請停下來想一想,這個地方是否更應該拋出一個異常


關注我,私信回復【資料】即可領取視頻中java相關資料以及一份227頁最新的bat大廠面試寶典

最後

歡迎大家一起交流,喜歡文章記得關注我點個讚喲,感謝支持!

相關焦點

  • 為什麼不建議你用去「!=null」做判空?
    為了避免空指針調用,我們經常會看到這樣的語句 最終,項目中會存在大量判空代碼,醜陋繁雜。。。如何避免這種情況?是否濫用了判空? 精華回答 這是初、中級程序猿經常會遇到的問題。
  • =null判空了
    ,null是令人頭痛的東西。時常會受到空指針異常(NPE)的騷擾。連Java的發明者都承認這是他的一項巨大失誤。有人說可以使用 JDK8提供的 Optional 來避免判空,但是用起來還是有些麻煩。作者在日常工作中,封裝了一個工具,可以可以鏈式調用對象成員而無需判空,相比原有的if null邏輯 和 JDK8提供的 Optional 更加優雅易用,在工程實踐中大大提高了編碼效率
  • =null判空,第4和5種你不知道
    項目中會存在大量判空代碼,多麼醜陋繁冗!如何避免這種情況?我們是否濫用了判空呢?Assert斷言private void xxxMethod(String key){ Assert.notNull(key); // do something}場景三:寫util類是否都需要逐級判斷空
  • java8之Optional 判空,簡化判空操作
    導語在沒有用Optional判空之前,你是否也像下面的代碼一樣判空呢?如果是,請往下看,Optional 相對傳統判空的優勢。傳統階層判空為什麼要用OptionalOptional 類是一個可以為null的容器對象。如果值存在則isPresent()方法會返回true,調用get()方法會返回該對象。Optional 是個容器:它可以保存類型T的值,或者僅僅保存null。Optional提供很多有用的方法,這樣我們就不用顯式進行空值檢測。Optional 類的引入很好的解決空指針異常。
  • =null)做非空判斷帶你快速上手Optional實戰性理解
    null!),所以就不用擔心空指針異常了2.5 Optional.filter()方法(過濾對象)filter()方法大致意思是,接受一個對象,然後對他進行條件過濾,如果條件符合則返回Optional對象本身,如果不符合則返回空Optional源碼:public Optional
  • =null」?
    問題 為了避免空指針調用,我們經常會看到這樣的語句 最終,項目中會存在大量判空代碼,多麼醜陋繁冗!如何避免這種情況?我們是否濫用了判空呢? 回答 這是初、中級程序猿經常會遇到的問題。
  • C++空指針使用nullptr代替NULL
    如果暫時不明確指針指向哪個變量,則可以賦予NULL,如:int* p = NULL;除了NULL之外,C++11新標準引入了nullptr來表示一個空指針。nullptr 既不是整型類型,也不是指針類型,nullptr 的類型是 std::nullptr_t,能轉換成任意的指針類型。
  • 如何避免在Vue中使用null作為class的空值
    使用 null 而不是傳遞一個空字符串-- <div> -->比較空字符串 &39; 和 null讓我們深入研究上面的示例,然後更全面地了解正在發生的事情。<div></div>&& 並沒有錯——事實上它正在做它的工作,只是我們需要一個具體的返回值。
  • =null」
    問題 為了避免空指針調用,我們經常會看到這樣的語句 最終,項目中會存在大量判空代碼,多麼醜陋繁冗!如何避免這種情況?我們是否濫用了判空呢? 回答 這是初、中級程序猿經常會遇到的問題。
  • 為什麼依賴注入對於程式設計師來說是件好事?
    預計學習時長12分鐘圖源:unsplash為什麼依賴注入對於程式設計師來說是件好事本文將用Kotlin編寫示例說明這一問題的,但其中並未使用該特殊語法功能,因此每位程式設計師都能理解。如果咖啡機不在咖啡館應該怎麼辦?如果有一個空白空間,每次想喝咖啡時,就必須從頭開始構造機器。
  • 高級程式設計師的自我修養:如何才能成長為牛逼的高級程式設計師?
    高級程式設計師的自我修養:牛逼的人總是讓人羨慕,身邊這樣的人實在太多太多,怎麼辦?王侯將相寧有種乎。作為程式設計師,面對牛逼的同類,其實我們也可以憤而追之:大丈夫當如是也。有自知之明、有夢想總是好的。關鍵是,如何才能成長為牛逼的高級程式設計師呢?下面和千鋒廣州小編一起來看看吧。
  • 關於Java String 類型轉換時null的問題
    開發中經常遇到從集合類List、Map中取出數據轉換為String的問題,這裡如果處理不好,經常會遇到空指針異常java.lang.NullPointerException,在此總結一下常用轉換為String的方法,以及轉換後如何對其進行判null使用的問題。
  • 你還在為解決代碼中的null而煩惱嗎?
    作為一個程式設計師,經常遇到的問題就是空指針異常,為了避免這個異常,代碼中會出現非常多的空值判斷,也因此引入了大量的if else進行控制判斷,java 8 中提供了Optional類來解決空指針的問題。那麼Optional類有什麼用呢? Optional 類是一個可以為null的容器對象。如果值存在則isPresent()方法會返回true,調用get()方法會返回該對象。
  • 3分鐘短文 | Laravel 查詢結果檢查是不是空,5個方法你別用錯
    那麼如何對所得結果判空呢?如果使用first方法,要麼返回一個Model對象,要麼返回null。寫起來是這樣的:$user = User::where(&39;, &39;, Input::get(&39;))->first();if ($user === null) { // 不存在}如果使用聚合查詢,通過查詢所得條目數,也可以判空。
  • 你學得會的:C語言中的null指針
    在非常高的層次上,我們可以將NULL視為null指針,它在C中用於各種目的。NULL的一些最常見用例是:1.在尚未為該指針變量分配任何有效內存地址時初始化該指針變量。2.在訪問任何指針變量之前檢查空指針。這樣,我們可以在與指針相關的代碼中執行錯誤處理,例如,僅當其不為NULL時才取消引用指針變量。3.當我們不想傳遞任何有效的內存地址時,將空指針傳遞給函數參數。
  • 資料庫允許空值(null),往往是悲劇的開始
    資料庫欄位允許空值,會遇到一些問題,此處包含的一些知識點,和大家聊一聊。null)。explain select * from user where id=1;索引欄位id上的等值查詢,能命中索引,如上圖所示:(1)type=ref,走非唯一索引;(2)rows=1,預估掃描1行;explain select * from user where id is null;索引欄位id上的null查詢,也能命中索引
  • 程式設計師:JSON學習,FastJson和Jackson對null的處理
    2、但是如果想把null對應的key序列化出來呢?的欄位,默認為falseWriteNullNumberAsZero—-數值欄位如果為null,輸出為0,而非nullWriteNullListAsEmpty—–List欄位如果為null,輸出為[],而非nullWriteNullStringAsEmpty—字符類型欄位如果為null,輸出為」「,而非nullWriteNullBooleanAsFalse–Boolean
  • 關於Java 字符串的全部,都在這份手冊裡了
    = null || str.trim().isEmpty();}03、第三方類庫在實際的項目開發當中,檢查字符串是否為空最常用的還是 Apache 的 commons-lang3 包,有各式各樣判空的方法。
  • 面試官:說說MySQL 中NULL和空值的區別?
    面試官:那你能大概說一下Mysql中 NULL值和空值的區別嗎?小木:(思考...)NULL和空值都用過,你要我說它兩有啥區別,這個我還真沒仔細想過,反正實際開發中會用!聽了小木的這個回答。我說:你這樣回答肯定是不妥的,這個問題你是必掛了。小木說: NULL翻譯過來不就是空嗎?我是真的沒有仔細想過,這個還是挺迷惑人的。