2011-04-14 60 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(); 
相关问题