2012-07-26 100 views
2

在將類嵌入爲其他類的屬性的常見情形中,檢查空值的最佳方法是什麼?在訪問屬性屬性的屬性時,檢查空值的正確方法是什麼?

爲了說明我在說什麼,說我想訪問this.getObject1().getObject2().someMethod()其中getObject1()getObject2()可能會返回null。現在我做了以下內容,它的醜陋,並必須有一個更好的辦法:

if (this.getObject1() != null) 
     if (this.getObject1().getObject2() != null) 
      if (this.getObject1().getObject2().someMethod()) 
       return whatever; 

爲了避免NPE,我必須在每一個步驟訪問的someMethod之前檢查空值()。什麼是更好的方法來完成這個?

+0

雖然不是100%相關,但您可能需要考慮閱讀空對象模式,因爲它可能與您的代碼有某些關聯。 http://en.wikipedia.org/wiki/Null_Object_pattern#Java – BlackVegetable 2012-07-26 21:15:39

+0

儘量避免這種風格 - 請參閱http://pragprog.com/articles/tell-dont-ask - 雖然我很欣賞那個庫或遺留代碼可能不會給你太多的選擇...... – DNA 2012-07-26 21:40:46

+0

在方法調用前你不需要'this.'。 – 2012-07-26 21:48:59

回答

1

這種風格是儘量要避免的 - 看到Law of Demeter - 儘管我明白,庫或遺留代碼可能不會離開你太多的選擇。

函數式編程語言(尤其是)通過使用OptionMaybe對象來避免此問題,它可以在某種程度上在Java中使用。例如,請參閱this article。對於eaxmple,可以使用Scala for-comprehensions簡潔地避免長序列的空檢查。但回到Java ...

理想情況下,假設你可以修改你調用的代碼,你會重組,所以你可以調用'外部'對象,然後調用'內部'對象,只有一個null在每個階段檢查。或者重構代碼以避免這種深層嵌套。

+0

我喜歡「告訴,不要問」的概念,但我會記住,但爲了避免NPE,在訪問該屬性的屬性之前,您必須詢問該對象的屬性是否爲空,對嗎?如果對象爲空,則無法「讓對象處理它」。 – 2012-07-27 12:34:21

+1

一種方法是創建一個您存儲的特殊「空對象」,而不是實際的空值。換句話說,您有一個超類或接口,帶有一個或多個「真實」子類,以及一個可以安全響應調用的特例「空子類」。 – DNA 2012-07-27 12:55:37

3

另一種方法是將每種方法的結果設置爲變量,以便您不必每次都重新調用該方法。所以,像這樣

Object obj1 = this.getObject1(); 
if (null != obj1) 
{ 
    Object obj2 = obj1.getObject2(); 
    if (null != ob2) 
    { 
     Object obj3 = obj2.someMethod(); 
     if (null != obj3) 
       return whatever; 
    } 
} 

如果方法不貴,你可以做這一切一樣if內像克里斯·納瓦的解決方案選擇更少的代碼

+0

這可能是一個改進(雖然答案可能措辭得更好。)編輯:好得多。 – BlackVegetable 2012-07-26 21:11:44

+0

謝謝你的建議。不過,我不確定這會提高可讀性,足以證明額外的代碼行。這是一種折騰。 – 2012-07-27 13:02:11

1

你可以把它簡化更多(至少更容易閱讀)像:

Object o1 = getObject1(); 
if(o1 != null) 
{ 
    Object o2 = getObject2(); 
    if(o2 != null) 
    { 
     if(o2.someMethod()) return whatever; 
    } 
} 
1

真的沒有太多的事情可以做。我的意思是,你可以將每一步分配給一個變量,但它最終會成爲更多的代碼,並且你可以用一個通用的方法來使用反射來完成它,但是它的性能會低得多,因爲不是真的好理由。

2

我用& &代替嵌套的if()s。它只是稍微更清潔(可以說),但仍然不是我想要的。

if (
    this.getObject1() != null 
    && 
    this.getObject1().getObject2() != null 
    && 
    this.getObject1().getObject2().someMethod() 
) { 
      return whatever; 
} 
+0

如果獲得的對象[相對]廉價和純粹(因爲結果是相同的)..這是我立即傾向於的方法,但我更喜歡在每個'&&' ; - )雖然一般我會盡量避免這種情況.. – 2012-07-26 21:23:39

+0

我同意。上面假設get()查找相對便宜。如果不是,那麼嵌套if()的局部變量是更好的選擇。我也同意整個情況是一種代碼味道。 – 2012-07-26 21:29:51