我有一个名为用户的域对象。用户的属性包括ssoId,name,email,createdBy,createdDate和userRole。其中, ssoId必须是唯一的,因为没有两个用户可以拥有相同的sso id。所以我的equals方法检查sso id并返回true或false。
@Override public boolean equals(Object o) {
if (!(o instanceof User))
return false;
return user.getSsoId().equals((User)o.getSsoId());
}
我觉得这是一个不正确的实现,尽管就业务规则而言是正确的。对于具有相同sso id但具有不同的名称或电子邮件或两者的值的两个对象,上述实现将返回true。我应该更改我的平等合同以检查所有字段的相等性吗?你的建议是什么?
答案 0 :(得分:17)
这对于“技术平等”(几乎)是正确的,但不是“自然平等”。为了实现最高技术平等,您还应该测试反身o == this
。可能会发生该对象尚未持久保存在DB中,因此尚未拥有技术ID。 E.g。
public class User {
private Long id;
@Override
public boolean equals(Object object) {
return (object instanceof User) && (id != null)
? id.equals(((User) object).id)
: (object == this);
}
@Override
public int hashCode() {
return (id != null)
? (User.class.hashCode() + id.hashCode())
: super.hashCode();
}
}
对于“自然平等”,您应该比较所有非技术属性。对于“真实世界的实体”来说,这比技术上的平等更加强大(但也更昂贵)。
public class User {
private String name;
private Date birth;
private int housenumber;
private long phonenumber;
@Override
public boolean equals(Object object) {
// Basic checks.
if (object == this) return true;
if (!(object instanceof User)) return false;
// Property checks.
User other = (User) object;
return Objects.equals(name, other.name)
&& Objects.equals(birth, other.birth)
&& (housenumber == other.housenumber)
&& (phonenumber == other.phonenumber);
}
@Override
public int hashCode() {
return Objects.hash(name, birth, housenumber, phonenumber);
}
}
是的,当有很多属性时,这就是很多代码。有点像IDE(Eclipse,Netbeans等)可以为您自动生成equals()
,hashCode()
(以及toString()
,getter和setter)。利用它。在Eclipse中,右键单击代码并查看 Source (Alt + Shift + S)菜单选项。
答案 1 :(得分:2)
如果在模型中ssoid必须是唯一的,这意味着对于两个User实例,其他字段的值不应该不同。如果要验证该假设,如果开销不是问题,则可以使用equals方法中的断言来执行此操作。
答案 2 :(得分:2)
您正在做的事情似乎很好,并且您没有违反equals
必须遵循的任何the rules。
您可能仍希望检查其他字段,而不是更改equals
的语义,而是检测业务逻辑中的不一致,并可能触发断言/异常。
答案 3 :(得分:2)
这是一个棘手的决定。
这是我几个月前考虑哈希时遇到的一个问题。我建议你阅读哈希是什么,因为它与你的答案高度相关...我建议你想要实现某种哈希并测试它的相等性。
存在不同类型的相等...对象的身份相等,对象的数据相等,整个对象的相等......你还可以在那里包含审计信息
事实是'平等'有许多可能的含义。
我通过在所有字段中实现相等的严格平等来解决这个问题,因为在询问它之后似乎是equals的直观含义。然后,我为我需要的其他类型的等式构造了方法,并定义了一个包装这些的接口。
我不会在object ==上测试相等性,因为通常你会使用相同的数据测试两个不同的对象,尽管它们指的是不同的内存地址,但我的书中它们是相同的。