正确的实施方式等于合同

我有一个名为User的域对象。 用户的属性包括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。 我应该更改我的等于合同以检查所有字段的相等性吗? 你的建议是什么?

这对于“技术平等”(几乎)是正确的,但不是“自然平等”。 为了达到最高技术平等,你还应该测试反身o == this 。 可能会发生该对象尚未持久保存在DB中,因此尚未拥有技术ID。 例如

 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() ,getters和setter)。 利用它。 在Eclipse中,右键单击代码并查看Source (Alt + Shift + S)菜单选项。

也可以看看:

  • JBoss:Equals和HashCode(考虑到持久性
  • Hibernate:Persistent Classes – 实现equals()和hashCode()
  • 相关问题:覆盖Java中的equals和hashCode

如果在模型中ssoid必须是唯一的,则意味着其他字段的值对于两个User实例不应该不同。 如果要validation该假设,如果开销不是问题,则可以使用equals方法中的断言来执行此操作。

你正在做的事似乎很好,你没有违反任何必须遵循的规则 。

您可能仍希望检查其他字段,而不是更改equals的语义,而是检测业务逻辑中的不一致,并可能触发断言/exception。

这是一个棘手的决定。

这是我几个月前考虑哈希时遇到的一个问题。 我建议你阅读哈希是什么,因为它与你的答案高度相关……我建议你想要实现某种哈希并测试它的相等性。

存在不同类型的相等…对象的身份相等,对象的数据相等,整个对象的相等……您还可以在其中包含审计信息。

事实上,“平等”有许多可能的含义。

我通过在所有字段中实现相等的严格平等来解决这个问题,因为在询问它之后似乎是等于的直观含义。 然后,我为我需要的其他类型的相等构造了方法,并定义了一个包装这些的接口。

我不会在object ==上测试相等性,因为通常你会使用相同的数据测试两个不同的对象,尽管它们指的是不同的内存地址,但在我的书中它们是相同的。