2011-04-14 66 views
20

我有一個地址對象,我想創建一個equals方法。我可以通過做類似下面的事情來簡化它(縮短一點):Java:在等號檢查中避免NullPointerException的乾淨方式

public boolean equals(Object obj) 
{ 
    if (this == obj) 
     return true; 

    if (obj == null) 
     return false; 

    if (getClass() != obj.getClass()) 
     return false; 

    Address other = (Address) obj; 

    return this.getStreet().equals(other.getStreet()) 
     && this.getStreetNumber().equals(other.getStreetNumber()) 
     && this.getStreetLetter().equals(other.getStreetLetter()) 
     && this.getTown().equals(other.getTown()); 
} 

問題是,其中一些可能爲空。換句話說,如果在此地址中沒有街道信件,我將獲得NullPointerException

如何在考慮空值的同時以乾淨的方式編寫此代碼?

+0

使用* @NotNull *註釋無處不在肯定會有所幫助。因此,使用空字符串和空數組,而不是空字符串和空數組來表示「空」的東西。空字符串是不包含字符的字符串。一個空數組是一個由零元素組成的數組。在我們的代碼庫中,「null」和NPE非常少見,其中* @NotNull *註釋在我們所有的每個類中都有使用:) – SyntaxT3rr0r 2011-04-14 10:52:01

+0

除此之外,與可變對象「相等」的概念沒有多大意義。使你的對象不可變。禁止空。一切都會更順暢。 – SyntaxT3rr0r 2011-04-14 10:53:24

+0

當然,如果我能的話,我會!問題在於,在這種情況下,這些東西*可能不存在。例如,並非所有地址都有一個字母,所以它應該是空的。關於不變性問題,我完全同意,但不幸的是,這不是我的選擇。如果這取決於我,那會是。 – Svish 2011-04-14 11:05:46

回答

15

您可以像使用

public static boolean isEqual(Object o1, Object o2) { 
    return o1 == o2 || (o1 != null && o1.equals(o2)); 
} 
+1

不錯,簡潔!雖然它不是'等於'嗎? – Svish 2011-04-14 12:49:06

+1

@Svish不一定。 _Is_對象o1 _equal_對象o2? – 2011-04-14 13:10:47

+1

@Octavian,好點...想些什麼,嘿嘿。 – Svish 2011-04-14 14:12:46

8

一個輔助方法,你可以做到以下幾點:

public boolean equals(Object obj) 
{ 
    if (this == obj) { 
     return true; 
    } 

    if (obj == null) { 
     return false; 
    } 

    if (getClass() != obj.getClass()) { 
     return false; 
    } 

    Address other = (Address) obj; 

    return equals(this.getStreet(),other.getStreet()) 
     && equals(this.getStreetNumber(), other.getStreetNumber()) 
     && equals(this.getStreetLetter(), other.getStreetLetter()) 
     && equals(this.getTown(), other.getTown()); 
} 

private boolean equals(Object control, Object test) { 
    if(null == control) { 
     return null == test; 
    } 
    return control.equals(test); 
} 

Java 7中引入了內置支持這個用例與java.util.Objects類見:

+0

@Jigar,爲什麼會更好?我認爲這看起來更清潔... – Svish 2011-04-14 11:06:24

+0

@Svish它會看起來更乾淨+它也將是最佳的。 – 2011-04-14 11:11:12

+0

@Jigar,我個人認爲它看起來更乾淨。但爲什麼它是最佳的?無論你看看它,你都有3項可能需要完成的檢查。如果他們中的任何一個經過,你會停止執行。有一些編譯器優化我不知道或什麼? – Svish 2011-04-14 11:13:47

1

有沒有真正乾淨的方式來做到這一點;最好的選擇可能是讓你的IDE爲你生成代碼。 Eclipse可以通過Source - > Generate hashCode()和equals()上下文菜單實現。

0

我會考慮將一些equals方法定義爲靜態類方法,比如說Street對象。這種方法你永遠不會嘗試調用null上的.equals()方法。

樣本函數可能看起來像:

public static boolean equals(Object one, Object two) 

此外,這是很好的做法,把支票像

if (obj == null) 
    return false; 

在函數的開始。

+0

是的,必須說我錯過了你在C#中的對象上的靜態'Equals'方法。在這種情況下會很方便。 – Svish 2011-04-14 11:08:07

7

Google Guava提供Objects.equal(Object, Object)其檢查平等考慮到無論是參數的可能爲空,而:

... 
return Objects.equal(this.getStreet(), other.getStreet()) 
    && Objects.equal(this.getStreetNumber(), other.getStreetNumber()) 
    && Objects.equal(this.getStreetLetter(), other.getStreetLetter()) 
    && Objects.equal(this.getTown(), other.getTown()); 

這也是值得指出的是對象具有實施hashCode()toString()其他輔助方法。

3

我有一個輔助類檢查W/A靜態方法:

public static boolean isEquals(final Object o1, final Object o2) { 
     return o1 == null ? o2 == null : o1.equals(o2); 
} 

所以,在equals方法,

return Checker.isEquals(this.getStreet(), other.getStreet()) 
     && Checker.isEquals(this.getStreetNumber(), other.getStreetNumber()) 
     && Checker.isEquals(this.getStreetLetter(), other.getStreetLetter()) 
     && Checker.isEquals(this.getTown(), other.getTown()); 
+0

我改稱爲「Checker」類「public class NullSafe」。 – 2011-04-21 07:09:03

0

Apache Commons Lang提供EqualsBuilder助手類的平等comparissons。還有一個用於哈希碼。

return new EqualsBuilder() 
.append(this.getStreet(), other.getStreet()) 
.append(this.getStreetNumber(), other.getStreetNumber() 
.append(this.getStreetLetter(), other.getStreetLetter()) 
.append(this.getTown(), other.getTown())).isEquals(); 
相關問題