简体   繁体   English

覆盖equals和hashCode只是为了调用super.equals / hashCode或引发AssertionError?

[英]Override equals and hashCode just to call super.equals/hashCode or throw AssertionError?

is there a best practice, when to override equals? 有什么最佳实践,何时覆盖等于?

Should I override equals/hashCode and throw an AssertionError? 我应该重写equals / hashCode并引发AssertionError吗? Just to be sure nobody uses that? 只是为了确保没有人使用? (as recommended in the book Effective Java) (如有效Java一书中所建议)

Should I override equals/hashCode and just invoke super.equals/hashCode, because the super class behaviour is the same wanted? 我是否应该重写equals / hashCode并仅调用super.equals / hashCode,因为超类的行为与所希望的相同? (FindBugs recommended this, because I added one field) (FindBugs建议这样做,因为我添加了一个字段)

Are they really best practices? 他们真的是最佳做法吗?

Errors 错误

You should not throw an an exception from the equals or hashCode methods. 您不应从equalshashCode方法引发异常。 The equals and hashCode methods are used everywhere, throwing exceptions indiscriminately here could harm you later. equals和hashCode方法无处不在,在这里乱扔异常可能会对以后造成伤害。

AssertionError Asse田

You should never throw AssertionError directly. 您永远不要直接抛出AssertionError Putting assert statements into any method is fine as these statements will not be run when assertions are turned off. assert语句放入任何方法都可以,因为在断言关闭时将不会运行这些语句。

When to Override 何时覆盖

There is no harm in overriding and passing straight on to super.equals() if the super class method is Object.equals . 如果超类方法是Object.equals ,则重写并直接传递给super.equals()没有什么害处。

If the two objects you are comparing are of different types then you may fall into the trap of breaking symmetry, ie where x.equals(y) is true but y.equals(x) is false. 如果要比较的两个对象属于不同类型,则可能会陷入破坏对称的陷阱,即x.equals(y)为true,而y.equals(x)为false。 This can happen if y is a subclass of x and so the equals method for y may do slightly different comparison. 如果y是x的子类,则可能发生这种情况,因此y的equals方法进行的比较可能略有不同。 You can check for this in your equals method by using if (getClass() != obj.getClass()) return false; 您可以通过使用if (getClass() != obj.getClass()) return false;来在equals方法中进行检查if (getClass() != obj.getClass()) return false; .

Best Practises 最佳实践

Effective Java is a great resource here, especially on how best to implement the hashCode() method. 在这里, 有效的Java是一个很好的资源,尤其是在如何最好地实现hashCode()方法方面。 Make sure that you read and take into account the contracts of equals and hashCode listed in the Javadoc and make sure if you override one, then override the other. 请确保您已阅读并考虑了Javadoc中列出的equalshashCode协定,并确保是否覆盖一个,然后覆盖另一个。 The "Generate hashCode() and equals" function in eclipse does a good job of providing what you need in those methods so check out the code it generates for your classes. eclipse中的“ Generate hashCode()and equals”函数在提供这些方法所需的功能方面做得很好,因此请检查它为类生成的代码。 The following is taken from the Javadoc of java.lang.Object . 以下内容摘自java.lang.ObjectJavadoc

equals Contract: 等于合约:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true. 这是自反的:对于任何非空参考值x,x.equals(x)应该返回true。
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true. 它是对称的:对于任何非空参考值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true。
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true. 它是可传递的:对于x,y和z的任何非空引用值,如果x.equals(y)返回true,而y.equals(z)返回true,则x.equals(z)应该返回true。
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified. 这是一致的:对于任何非空引用值x和y,只要未修改对象的equals比较中使用的信息,对x.equals(y)的多次调用将始终返回true或始终返回false。
  • For any non-null reference value x, x.equals(null) should return false. 对于任何非null参考值x,x.equals(null)应该返回false。

hashCode Contract: hashCode合同:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. 在Java应用程序的执行过程中,只要在同一对象上多次调用它,则hashCode方法必须一致地返回相同的整数,前提是未修改该对象的equals比较中使用的信息。 This integer need not remain consistent from one execution of an application to another execution of the same application. 从一个应用程序的执行到同一应用程序的另一执行,此整数不必保持一致。
  • 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方法必须产生相同的整数结果。
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. 根据equals(java.lang.Object)方法,如果两个对象不相等,则不需要在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。 However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables. 但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

If you need to compare two objects in the same class, you should override equals with your own implementation. 如果需要比较同一类中的两个对象,则应使用自己的实现重写equals。 If you are overriding equals, you should provide an implementation for hashCode as well. 如果要覆盖等于,则还应该提供hashCode的实现。 There is no point in overriding the methods just to invoke super, as that is the default behavior. 仅仅为了调用super而覆盖方法是没有意义的,因为这是默认行为。 I would not override the methods to throw an AssertionError as that means you can never compare the objects for equality or use them in a HashMap. 我不会重写引发AssertionError的方法,因为这意味着您永远无法比较对象的相等性或在HashMap中使用它们。 There are other implications in the Collections classes as well in that case. 在这种情况下,Collections类也有其他含义。

Overriding equals and hashCode and then calling the super classes implementations with super.equals() to me is just a very clear way of documenting that you have thought about it and think the super class implementations are still perfectly valid. 覆盖equalshashCode ,然后使用super.equals()调用超类实现只是一种非常清晰的记录方式,可以证明您已经考虑过并且认为超类实现仍然完全有效。 Personally I don't see any issue with just documenting this in the class JavaDoc and skip adding the equals & hashCode. 就我个人而言,仅在类JavaDoc中进行记录并跳过添加equals和hashCode的操作就不会有任何问题。

Throwing AssertionError is a little extreme and isn't quite covered by the principle of least surprise. 引发AssertionError有点极端,并且没有被“最小惊喜”原则所涵盖。 If it is really an error to call equals() or hashCode() on your object use UnSupportedOperationException instead. 如果确实是在对象上调用equals()hashCode()的错误,请改用UnSupportedOperationException

If the object that you are extending does support equality it my be a good idea to support it your self, by calling super.equals() and then comparing the additional members that you have added. 如果您要扩展的对象确实支持相等,那么我最好通过调用super.equals()然后比较您添加的其他成员来支持自己。

I override equals and hashCode for all objects that will be used in java.util Collections API. 我为将在java.util Collections API中使用的所有对象覆盖equals和hashCode。 Those classes usually depend on proper overrides. 这些类通常取决于适当的替代。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM