开发者

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? Just to be sure nobody uses that? (as recommended in the book Effective Java)

Should I override equals/hashCode and just invoke super.equals/hashCode, beca开发者_运维技巧use the super class behaviour is the same wanted? (FindBugs recommended this, because I added one field)

Are they really best practices?


Errors

You should not throw an an exception from the equals or hashCode methods. The equals and hashCode methods are used everywhere, throwing exceptions indiscriminately here could harm you later.

AssertionError

You should never throw AssertionError directly. Putting assert statements into any method is fine as these statements will not be run when assertions are turned off.

When to Override

There is no harm in overriding and passing straight on to super.equals() if the super class method is Object.equals.

If the two objects you are comparing are of different types then you may fall into the trap of breaking symmetry, i.e. where x.equals(y) is true but y.equals(x) is false. This can happen if y is a subclass of x and so the equals method for y may do slightly different comparison. You can check for this in your equals method by using if (getClass() != obj.getClass()) return false;.

Best Practises

Effective Java is a great resource here, especially on how best to implement the hashCode() method. 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. 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. The following is taken from the Javadoc of java.lang.Object.

equals Contract:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return 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.
  • 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.
  • 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.
  • For any non-null reference value x, x.equals(null) should return false.

hashCode Contract:

  • 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. 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.
  • 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. 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. If you are overriding equals, you should provide an implementation for hashCode as well. There is no point in overriding the methods just to invoke super, as that is the default behavior. 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. There are other implications in the Collections classes as well in that case.


I override equals and hashCode for all objects that will be used in java.util Collections API. Those classes usually depend on proper overrides.


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. Personally I don't see any issue with just documenting this in the class JavaDoc and skip adding the equals & hashCode.

Throwing AssertionError is a little extreme and isn't quite covered by the principle of least surprise. If it is really an error to call equals() or hashCode() on your object use UnSupportedOperationException instead.

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜