commons/lang 构建器非常棒,我多年来一直在使用它们,而没有明显的性能开销(有和没有休眠)。但正如 Alain 所写,Guava 方式更好:
这是一个示例 Bean:
public class Bean{
private String name;
private int length;
private List<Bean> children;
}
这里是用 Commons/Lang 实现的 equals() 和 hashCode():
@Override
public int hashCode(){
return new HashCodeBuilder()
.append(name)
.append(length)
.append(children)
.toHashCode();
}
@Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other = (Bean) obj;
return new EqualsBuilder()
.append(name, other.name)
.append(length, other.length)
.append(children, other.children)
.isEquals();
} else{
return false;
}
}
这里使用 Java 7 或更高版本(受 Guava 启发):
@Override
public int hashCode(){
return Objects.hash(name, length, children);
}
@Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other = (Bean) obj;
return Objects.equals(name, other.name)
&& length == other.length // special handling for primitives
&& Objects.equals(children, other.children);
} else{
return false;
}
}
注意:这段代码最初引用了 Guava,但正如 cmets 所指出的,该功能已经在 JDK 中引入,因此不再需要 Guava。
如您所见,Guava / JDK 版本更短,并且避免了多余的辅助对象。在 equals 的情况下,如果早期的 Object.equals() 调用返回 false,它甚至允许短路评估(公平地说:commons / lang 有一个具有相同语义的 ObjectUtils.equals(obj1, obj2) 方法,可以用来代替 EqualsBuilder 到允许如上所述的短路)。
所以:是的,commons lang 构建器比手动构建的 equals() 和 hashCode() 方法(或者 Eclipse 将为您生成的那些可怕的怪物)更可取,但 Java 7+ / Guava 版本更好。
还有关于 Hibernate 的说明:
在 equals()、hashCode() 和 toString() 实现中使用惰性集合时要小心。如果您没有打开的 Session,那将会惨遭失败。
注意(关于equals()):
a) 在上述两个版本的 equals() 中,您可能还想使用这些快捷方式中的一个或两个:
@Override
public boolean equals(final Object obj){
if(obj == this) return true; // test for reference equality
if(obj == null) return false; // test for null
// continue as above
b) 根据您对 equals() 合约的解释,您还可以更改行
if(obj instanceof Bean){
到
// make sure you run a null check before this
if(obj.getClass() == getClass()){
如果您使用第二个版本,您可能还想在您的equals() 方法中调用super(equals())。这里意见不一,这个话题在这个问题中讨论:
right way to incorporate superclass into a Guava Objects.hashcode() implementation?
(虽然是关于hashCode(),但同样适用于equals())
注意(灵感来自 kayahr 的评论)
Objects.hashCode(..)(就像底层的Arrays.hashCode(...))如果有很多原始字段,可能会表现不佳。在这种情况下,EqualsBuilder 实际上可能是更好的解决方案。