I have always thought that the .equals() method in java should be overridden to be made specific to the class you have created. In other words to look for equivalence of two different instances rather than two references to the same instance. However I have encountered other programmers who seem to think that the default object behavior should be left alone and a new method created for testing equivalence of two objects of the same class.
我一直认为应该重写java中的.equals()方法,使其特定于您创建的类。换句话说,寻找两个不同实例的等价而不是两个对同一实例的引用。但是我遇到过其他程序员,他们似乎认为应该保留默认对象行为并创建一个新方法来测试同一个类的两个对象的等价性。
What are the argument for and against overriding the equals method?
支持和反对覆盖equals方法的理由是什么?
7 个解决方案
#1
19
Overriding the equals method is necessary if you want to test equivalence in standard library classes (for example, ensuring a java.util.Set contains unique elements or using objects as keys in java.util.Map objects).
如果要在标准库类中测试等效性(例如,确保java.util.Set包含唯一元素或使用对象作为java.util.Map对象中的键),则必须覆盖equals方法。
Note, if you override equals, ensure you honour the API contract as described in the documentation. For example, ensure you also override Object.hashCode:
请注意,如果您覆盖等于,请确保遵守文档中所述的API合同。例如,确保您还重写Object.hashCode:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须生成相同的整数结果。
EDIT: I didn't post this as a complete answer on the subject, so I'll echo Fredrik Kalseth's statement that overriding equals works best for immutable objects. To quote the API for Map:
编辑:我没有发布这个作为主题的完整答案,所以我将回应Fredrik Kalseth的声明,即重写equals最适合不可变对象。引用Map的API:
Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.
注意:如果将可变对象用作映射键,则必须非常小心。如果在对象是地图中的键的同时以影响等于比较的方式更改对象的值,则不指定映射的行为。
#2
8
I would highly recommend picking up a copy of Effective Java and reading through item 7 obeying the equals contract. You need to be careful if you are overriding equals for mutable objects, as many of the collections such as Maps and Sets use equals to determine equivalence, and mutating an object contained in a collection could lead to unexpected results. Brian Goetz also has a pretty good overview of implementing equals and hashCode.
我强烈建议您阅读有效Java的副本,并阅读遵守平等合同的第7项。如果要覆盖可变对象的equals,则需要小心,因为许多集合(如Maps和Sets)使用equals来确定等价,并且对集合中包含的对象进行变更可能会导致意外结果。 Brian Goetz对实现equals和hashCode也有很好的概述。
#3
4
You should "never" override equals & getHashCode for mutable objects - this goes for .net and Java both. If you do, and use such an object as the key in f.ex a dictionary and then change that object, you'll be in trouble because the dictionary relies on the hashcode to find the object.
你应该“永远”覆盖可变对象的equals和getHashCode - 这适用于.net和Java。如果你这样做,并使用这样的对象作为f.ex中的键,然后更改该对象,那么你将遇到麻烦,因为字典依赖于哈希码来查找对象。
Here's a good article on the topic: http://weblogs.asp.net/bleroy/archive/2004/12/15/316601.aspx
这是一篇关于这个主题的好文章:http://weblogs.asp.net/bleroy/archive/2004/12/15/316601.aspx
#4
2
@David Schlosnagle mentions mentions Josh Bloch's Effective Java -- this is a must-read for any Java developer.
@David Schlosnagle提到了Josh Bloch的Effective Java - 这对任何Java开发人员来说都是必读的。
There is a related issue: for immutable value objects, you should also consider overriding compare_to
. The standard wording for if they differ is in the Comparable API:
存在一个相关问题:对于不可变值对象,您还应考虑重写compare_to。如果它们不同的标准措辞在Comparable API中:
It is generally the case, but not strictly required that (compare(x, y)==0) == (x.equals(y)). Generally speaking, any comparator that violates this condition should clearly indicate this fact. The recommended language is "Note: this comparator imposes orderings that are inconsistent with equals."
通常情况是这样,但并非严格要求(compare(x,y)== 0)==(x.equals(y))。一般来说,任何违反此条件的比较器都应清楚地表明这一事实。推荐的语言是“注意:这个比较器强加了与equals不一致的排序。”
#5
0
The Equals method is intended to compare references. So it should not be overriden to change its behaviour.
Equals方法用于比较参考。所以不应该重写它来改变它的行为。
You should create a new method to test for equivalence in different instances if you need to (or use the CompareTo method in some .NET classes)
如果需要(或在某些.NET类中使用CompareTo方法),您应该创建一个新方法来测试不同实例中的等价性
#6
0
To be honest, in Java there is not really an argument against overriding equals. If you need to compare instances for equality, then that is what you do.
说实话,在Java中并没有真正反对压倒等于的论点。如果您需要比较实例是否相等,那么您就是这么做的。
As mentioned above, you need to be aware of the contract with hashCode, and similarly, watch out for the gotchas around the Comparable interface - in almost all situations you want the natural ordering as defined by Comparable to be consistent with equals (see the BigDecimal api doc for the canonical counter example)
如上所述,您需要了解与hashCode的契约,同样,请注意Comparable接口周围的问题 - 在几乎所有情况下,您都希望Comparable定义的自然顺序与equals一致(请参阅BigDecimal)规范计数器示例的api doc)
Creating a new method for deciding equality, quite apart from not working with the existing library classes, flies in the face of Java convention somewhat.
除了不使用现有的库类之外,创建一个用于决定相等性的新方法,在某种程度上面对Java约定。
#7
0
You should only need to override the equals()
method if you want specific behaviour when adding objects to sorted data structures (SortedSet
etc.)
如果在将对象添加到已排序的数据结构时需要特定的行为,则只需要覆盖equals()方法(SortedSet等)
When you do that you should also override hashCode()
.
当你这样做时,你也应该覆盖hashCode()。
See here for a complete explanation.
请参阅此处以获取完整说明。
#1
19
Overriding the equals method is necessary if you want to test equivalence in standard library classes (for example, ensuring a java.util.Set contains unique elements or using objects as keys in java.util.Map objects).
如果要在标准库类中测试等效性(例如,确保java.util.Set包含唯一元素或使用对象作为java.util.Map对象中的键),则必须覆盖equals方法。
Note, if you override equals, ensure you honour the API contract as described in the documentation. For example, ensure you also override Object.hashCode:
请注意,如果您覆盖等于,请确保遵守文档中所述的API合同。例如,确保您还重写Object.hashCode:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须生成相同的整数结果。
EDIT: I didn't post this as a complete answer on the subject, so I'll echo Fredrik Kalseth's statement that overriding equals works best for immutable objects. To quote the API for Map:
编辑:我没有发布这个作为主题的完整答案,所以我将回应Fredrik Kalseth的声明,即重写equals最适合不可变对象。引用Map的API:
Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.
注意:如果将可变对象用作映射键,则必须非常小心。如果在对象是地图中的键的同时以影响等于比较的方式更改对象的值,则不指定映射的行为。
#2
8
I would highly recommend picking up a copy of Effective Java and reading through item 7 obeying the equals contract. You need to be careful if you are overriding equals for mutable objects, as many of the collections such as Maps and Sets use equals to determine equivalence, and mutating an object contained in a collection could lead to unexpected results. Brian Goetz also has a pretty good overview of implementing equals and hashCode.
我强烈建议您阅读有效Java的副本,并阅读遵守平等合同的第7项。如果要覆盖可变对象的equals,则需要小心,因为许多集合(如Maps和Sets)使用equals来确定等价,并且对集合中包含的对象进行变更可能会导致意外结果。 Brian Goetz对实现equals和hashCode也有很好的概述。
#3
4
You should "never" override equals & getHashCode for mutable objects - this goes for .net and Java both. If you do, and use such an object as the key in f.ex a dictionary and then change that object, you'll be in trouble because the dictionary relies on the hashcode to find the object.
你应该“永远”覆盖可变对象的equals和getHashCode - 这适用于.net和Java。如果你这样做,并使用这样的对象作为f.ex中的键,然后更改该对象,那么你将遇到麻烦,因为字典依赖于哈希码来查找对象。
Here's a good article on the topic: http://weblogs.asp.net/bleroy/archive/2004/12/15/316601.aspx
这是一篇关于这个主题的好文章:http://weblogs.asp.net/bleroy/archive/2004/12/15/316601.aspx
#4
2
@David Schlosnagle mentions mentions Josh Bloch's Effective Java -- this is a must-read for any Java developer.
@David Schlosnagle提到了Josh Bloch的Effective Java - 这对任何Java开发人员来说都是必读的。
There is a related issue: for immutable value objects, you should also consider overriding compare_to
. The standard wording for if they differ is in the Comparable API:
存在一个相关问题:对于不可变值对象,您还应考虑重写compare_to。如果它们不同的标准措辞在Comparable API中:
It is generally the case, but not strictly required that (compare(x, y)==0) == (x.equals(y)). Generally speaking, any comparator that violates this condition should clearly indicate this fact. The recommended language is "Note: this comparator imposes orderings that are inconsistent with equals."
通常情况是这样,但并非严格要求(compare(x,y)== 0)==(x.equals(y))。一般来说,任何违反此条件的比较器都应清楚地表明这一事实。推荐的语言是“注意:这个比较器强加了与equals不一致的排序。”
#5
0
The Equals method is intended to compare references. So it should not be overriden to change its behaviour.
Equals方法用于比较参考。所以不应该重写它来改变它的行为。
You should create a new method to test for equivalence in different instances if you need to (or use the CompareTo method in some .NET classes)
如果需要(或在某些.NET类中使用CompareTo方法),您应该创建一个新方法来测试不同实例中的等价性
#6
0
To be honest, in Java there is not really an argument against overriding equals. If you need to compare instances for equality, then that is what you do.
说实话,在Java中并没有真正反对压倒等于的论点。如果您需要比较实例是否相等,那么您就是这么做的。
As mentioned above, you need to be aware of the contract with hashCode, and similarly, watch out for the gotchas around the Comparable interface - in almost all situations you want the natural ordering as defined by Comparable to be consistent with equals (see the BigDecimal api doc for the canonical counter example)
如上所述,您需要了解与hashCode的契约,同样,请注意Comparable接口周围的问题 - 在几乎所有情况下,您都希望Comparable定义的自然顺序与equals一致(请参阅BigDecimal)规范计数器示例的api doc)
Creating a new method for deciding equality, quite apart from not working with the existing library classes, flies in the face of Java convention somewhat.
除了不使用现有的库类之外,创建一个用于决定相等性的新方法,在某种程度上面对Java约定。
#7
0
You should only need to override the equals()
method if you want specific behaviour when adding objects to sorted data structures (SortedSet
etc.)
如果在将对象添加到已排序的数据结构时需要特定的行为,则只需要覆盖equals()方法(SortedSet等)
When you do that you should also override hashCode()
.
当你这样做时,你也应该覆盖hashCode()。
See here for a complete explanation.
请参阅此处以获取完整说明。