Right way to implement equals contract
我有一个叫做用户的域对象。用户的属性包括ssoid、name、email、createdby、createddate和userrole。其中,SSOID必须是唯一的,因为没有两个用户可以拥有相同的SSO ID。因此,我的equals方法检查SSO ID,并返回true或false。
1 2 3 4 5 | @Override public boolean equals(Object o) { if (!(o instanceof User)) return false; return user.getSsoId().equals((User)o.getSsoId()); } |
我认为这是一个不正确的实现,尽管就业务规则而言它是正确的。对于具有相同SSO ID但具有不同名称或电子邮件或两者的值的两个对象,上述实现将返回true。我应该改变我的平等合同来检查所有领域的平等吗?你有什么建议?
这对"技术平等"几乎是正确的,但对"自然平等"则不是正确的。为了实现最高的技术平等,您还应该测试反射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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(); } } |
对于"自然平等",你应该比较所有非技术性质。对于"现实世界的实体",这毕竟比技术平等更强大(但也更昂贵)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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等)可以为您自动生成
- jboss:equals和hashcode(考虑到持久性)
- 休眠:持久类-实现equals()和hashcode()。
- 相关问题:在Java中重写等值和哈希代码
这是一个棘手的决定。
这是我几个月前考虑散列时遇到的问题。我建议你读一读哈希是什么,因为它与你的答案高度相关…我建议您希望实现某种散列并测试其相等性。
有各种各样的平等…有对象的同一性的平等,对象的数据的平等,整个对象的平等…您还可以在其中包括审计信息。
事实上,"平等"有许多可能的含义。
我通过在所有领域实现一个严格的平等来解决这个问题,仅仅是因为在询问之后,它似乎是平等的直观含义。然后,我为我需要的其他类型的等式构造了方法,并定义了一个包装这些等式的接口。
我不会在object==上测试相等性,因为通常您使用相同的数据测试两个不同的对象,在我的书中,尽管它们引用了不同的内存地址,但数据是相等的。
你所做的似乎很好,而且你没有违反任何
您可能仍然希望检查其他字段,而不是更改
如果在您的模型中,ssoid必须是唯一的,这意味着对于用户的两个实例,其他字段的值不应该不同。如果您想验证这个假设,那么可以使用equals方法中的断言进行验证,前提是开销不是问题。