我有一个名为User的域对象。用户的属性包括ssoId,名称,电子邮件,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。该对象可能尚未持久存储在数据库中,因此还没有技术ID。例如
o == this
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)菜单选项。
equals()
hashCode()
toString()