java 中 if (someobject != null) 檢查對象是否為空白的問題

來源:互聯網
上載者:User

先我們來看下面代碼,對於這樣的對象為空白的檢查:

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

為了避免null 指標異常,看起來也沒什麼不妥。不過代碼裡面一片一片的對象是否為空白的判斷,實在難看。

對象是否為空白的契約

通常我們在定義API的時候,是遵循一些規矩的,這些規矩可以叫做規約,比如這樣的介面:

public Set<String> getCollections();

通常情況下,或者說沒有特殊說明的情況下,返回的set是不能為null的,如果沒有元素,應當是一個EmptySet才對。介面上下遊都遵守這樣的規約了,那麼一些防禦性代碼就可以省掉。所以嚴格來說,返回是否為空白,應當加入到API的文檔中去,在返回為空白時,需要聲明其特殊意義。對象為空白,經常能夠表達特殊含義:

public void updateUser(User user);

比如這樣的方法,要更新user的資訊,user有一個屬性age,類型Integer,當它為空白的時候,表示忽略該屬性,不更新。如果使用原語類型int就需要使用某種特殊值了,沒有Integer來得自然。

其他語言的改進

在Groovy中,使用問號這樣一個文法糖,使得代碼判空的邏輯得到最簡化:

def streetName = user?.address?.street

上面的代碼中,如果user為空白,是不會訪問它的address成員的,如果address為空白,則是不會訪問street的。

在Objective C中,方法調用變成了訊息傳遞機制,在往nil傳遞訊息的時候,除了返回0並沒有什麼副作用發生。關於“空”,在Objective C當中有這樣四種:



NULL來自於C語言的null 指標;nil是一個指向空的對象;Nil和nil類似,只不過它是一個指向空的類;NSNull是用來解決集合元素沒法放空元素的問題的,它就相當於空元素的一個封裝,在集合中表示一個空元素。

Scala中有一個Option抽象類別,它是強型別的,即Option[T],這個類型一旦被定義就不能改變。它下面有兩個子類,Some和None,None是一個表示空的單例對象,而Some存放的是實際結果:

def show(x: Option[String]) = x match {
  case Some(s) => s
  case None => "?"
}

編譯期間發現對象為空白的問題

在JSR 305: Annotations for Software Defect Detection中,最初來自於FindBug和IntelliJ的靈感,說白了就是@NonNull和@CheckForNull這兩個註解:

如果有這樣的方法定義:

void someMethod(@NotNull someParameter) { }

那麼,在調用的時候,這樣的代碼會直接編譯失敗的:

someMethod(null);

反之,定義這樣的方法:

@Nullable iWantToDestroyEverything() { return null; }

那麼這樣未經檢查的方法調用也會在編譯期間失敗:
1
   
iWantToDestroyEverything().something();

也就是說,在編譯時間就找出潛在的NPE問題。

對象為空白的檢查

不需要自己寫防禦性質的判斷語句來處理Null 物件了。比如JDK7的Objects對象:

this.child = Objects.requireNonNull(child, "it is empty");

這會在對象不為空白時完成指派陳述式,對象為空白時拋出訊息為“it is empty”的異常。

Jarkata Commons的API也提供了檢查對象是否為空白的方法;或者,你可以用Java原生的assert關鍵字。

NPE也受歡迎

比如這樣的代碼:

public Photo getGirlfriendPhoto() {
    try {
        return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName());
    } catch (NullPointerException e) {
        return null;
    }
}

如果要避免NPE,就可能會寫成類似這樣的代碼:

public Photo getGirlfriendPhoto() {
    if(appContext != null) {
        if(appContext.getPhotoDataSource() != null) {
            if(me != null) {
                if(me.getGirlfriend() != null) {
                    if(me.getGirlfriend().getName() != null){
                        // finally we are arrived
                        return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName());
                    }
                }
            }
        }
    }
 
    return null;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.