java 实施平等合同的正确方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3181339/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Right way to implement equals contract
提问by chedine
I have a domain object called User. Properties of user include ssoId, name, email, createdBy, createdDate and userRole. Of these, ssoId must be uniquein 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.
我有一个名为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());
}
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?
我觉得这是一个不正确的实现,尽管就业务规则而言它是正确的。对于具有相同 sso id 但名称或电子邮件或两者具有不同值的两个对象,上述实现将返回 true。我应该更改我的 equals 合同以检查所有字段的相等性吗?你的建议是什么?
采纳答案by BalusC
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.
这对于“技术平等”来说(几乎)是正确的,但对于“自然平等”来说则不然。为了实现顶级技术平等,您还应该测试自反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();
}
}
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);
}
}
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.
确实,当有很多属性时,这需要很多代码。有点像样的 IDE(Eclipse、Netbeans 等)可以为您自动生成equals(), hashCode()(以及toString()getter 和 setter)。从中受益。在 Eclipse 中,右键单击代码并查看Source(Alt+Shift+S) 菜单选项。
See also:
也可以看看:
回答by btreat
If in your model ssoid must be unique, that implies that the values for the other fields should not be different for two instances of User. If you want to validate that assumption, you could do so with assertions within the equals method if the overhead is not an issue.
如果在您的模型中 ssoid 必须是唯一的,这意味着对于 User 的两个实例,其他字段的值不应不同。如果您想验证该假设,如果开销不是问题,您可以使用 equals 方法中的断言来验证。
回答by casablanca
What you're doing seems fine, and you're not violating any of the rulesthat equalsmust follow.
你在做什么似乎罚款,而你没有违反任何规则是equals必须遵守。
You may still want to check other fields, not to change equals's semantics, but to detect an inconsistency in your business logic, and possibly trigger an assertion/exception.
您可能仍想检查其他字段,而不是更改equals的语义,而是检测业务逻辑中的不一致,并可能触发断言/异常。
回答by John Nicholas
This is a tricky decision to make.
这是一个棘手的决定。
This is a spot i got into when considering hashing a few months ago. I would suggest you read up on what a hash is because it is highly relevant to your answer ... i suggest that you are looking to implement some kind of hash and test its equality.
这是我几个月前考虑散列时遇到的一个问题。我建议您阅读散列是什么,因为它与您的答案高度相关……我建议您正在寻求实现某种散列并测试其相等性。
There are different kinds of equality ... there is the equality of the identity of the object, the equality of the data of the object, the equality of the entire object ... you could also include audit information in there also.
有不同种类的平等……有对象身份的平等、对象数据的平等、整个对象的平等……你也可以在其中包含审计信息。
The fact is that 'equal' has many possible meanings.
事实上,“平等”有许多可能的含义。
I resolved this by implementing equal as a strict equality across all fields simply because after asking around it seems to be the intuitive meaning of equals. I then constructed methos for the other kinds of equality i required and defined an interface to wrap these.
我通过在所有领域实现相等作为严格相等来解决这个问题,只是因为在询问之后它似乎是 equals 的直观含义。然后我为我需要的其他类型的平等构建了方法,并定义了一个接口来包装这些。
I wouldnt test equality on object == this because often you are testing two different objects with the same data which in my book are equal despite them referring to different memory addresses.
我不会在 object == this 上测试相等性,因为通常您正在测试具有相同数据的两个不同对象,尽管它们指的是不同的内存地址,但在我的书中它们是相等的。

