正确的实施方式等于合同 [英] Right way to implement equals contract
问题描述
我有一个名为用户的域对象。用户的属性包括ssoId,name,email,createdBy,createdDate和userRole。其中, ssoId必须是唯一的,因为没有两个用户可以拥有相同的sso id。所以我的equals方法检查sso id并返回true或false。
I have a domain object called User. Properties of user include ssoId, name, email, createdBy, createdDate and userRole. Of these, ssoId must be unique in the sense no two users can have the same sso id. So my equals method checks for the sso id and returns either true or false.
@Override public boolean equals(Object o) {
if (!(o instanceof User))
return false;
return user.getSsoId().equals((User)o.getSsoId());
}
我觉得这是一个不正确的实现,尽管它是正确的就业务规则而言。对于具有相同sso id但具有不同的名称或电子邮件或两者的值的两个对象,上述实现将返回true。我应该更改我的等于合同以检查所有字段的相等性吗?你的建议是什么?
What I feel is that this is an incorrect implementation, though it is correct as far as the business rules are concerned. The above implementation will return true for two objects with same sso id but with different values for say name or email or both. Should I change my equals contract to check the equality of all fields? What is your suggestion?
推荐答案
这对于技术平等来说(几乎)是正确的,但不是自然平等。要实现最高技术平等,您还应该测试反身 o == this
。可能会发生该对象尚未持久保存在DB中,因此尚未拥有技术ID。例如,
This is (almost) correct for "technical equality", but not for "natural equality". To achieve top technical equality, you should also test the reflexive o == this
. It may happen that the object isn't persisted in DB yet and thus doesn't have a technical ID yet. 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();
}
}
对于自然平等,你应该而是比较所有非技术属性。对于真实世界实体而言,这比技术上的平等更加强大(但也更昂贵)。
For "natural equality" you should rather compare all non-technical properties. For "real world entities" this is after all more robust (but also more expensive) than technical equality.
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)菜单选项。
True, that's lot of code when there are a lot of properties. A bit decent IDE (Eclipse, Netbeans, etc) can just autogenerate equals()
, hashCode()
(and also toString()
, getters and setters) for you. Take benefit of it. In Eclipse, rightclick code and peek the Source (Alt+Shift+S) menu option.
- JBoss的:等于和hashCode(在视图持久性)
- Hibernate:Persistent Classes - 实现equals()和hashCode()
- 相关问题:覆盖Java中的equals和hashCode
- JBoss: Equals and HashCode (in view of persistence)
- Hibernate: Persistent Classes - implementing equals() and hashCode()
- Related SO question: Overriding equals and hashCode in Java
这篇关于正确的实施方式等于合同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!