Follow general conventions when overriding equals

Reprinted: https://www.cnblogs.com/wangliyue/p/4448085.html

== is physical equality

equals is logical equality

Because instance objects of each class are inherently unique, using physical equality (==) means that an instance can only be equal to itself.

The use of logical equality is (equals) refers to whether an instance is equal to some key fields of another instance, so as to judge whether the two instances are equal.

The implementation of the equals method of the Object class: if they are physically equal, they are logically equal.

When is it unnecessary to override equals method of Object class?

1. It is hoped that the instance of this class can only be equal to itself, does not override the equals method, and only inherits the equals method of the Object class.

We compare whether the instance objects of this class are equal, whether using == or equals is actually a physical equality judgment.

2. The superclass of this class has already overridden the equals method of the Object class, and this class inherits the equals method of the superclass, which is also suitable for itself. In this case, the equals method is not overridden.

For example, the Set implementation classes all inherit the equals method of the AbstractSet class, the List implementation classes all inherit the equals method of the AbstractList class, and the Map implementation classes all inherit the equals method of the AbstractMap class.

3. Make sure that the equals method of this class will never be called.

When do you need to override the equals method of the Object class?

When a class needs its own unique "logical equality", for example, when we want some key fields of two instances to be equal, we consider them to be logically equal, and call the equals method to return true.

If you do not override the equals method and inherit the equals method of the Object class, the actual physical equality judgment is performed, that is, an instance can only be equal to itself.

For example: some "value classes", such as Integer, Date, String, etc. For these classes, when we call their equals method, we hope that as long as the key fields of the two instances are equal, it will return true, not that the two instances are the same instance. return true when And the equals method of these classes must be overridden, so that when used as the key of the Map collection, or the element of the Set collection, the expected result, because their equals method will be called to determine whether the two instances are logically equal.

But for some instance-controlled classes, such as singleton classes and enumeration classes, these classes do not need to override the equals method.

Correctly overriding the equals method requires following its general convention:

1. Reflexivity: x.equals(x) must return true. The instances themselves must be logically equal.

2. Symmetry: x.equals(y) and y.equals(x) should return the same result, both true or false.

3. Transitivity: x.equals(y) returns true, y.equals(z) returns true, then x.equals(z) should return true.

4. Consistency: As long as the key attribute values ​​of the compared instance objects have not changed, the results returned by the equals method should be the same and consistent no matter how many times the equals method is called.

5. For non-null instances of x, x.equals(null) always returns false.

The above five agreements are very important. There are many classes, including all collection classes, that depend on whether the instance objects passed to them obey the equals convention.

Combining all the convention requirements, get the trick for implementing a high-quality equals method:

1. Use the == operator to check "whether the reference to the parameter object is the same reference to the calling object". If yes, return true.

2. Use the instanceof operator to check whether the type of the parameter object is correct. The correct type here generally refers to verifying whether the type of the parameter object is the current class. Some cases can also be compared between other implementation classes of the interface implemented by the current class.

3. Convert the parameter object to the correct type. The type conversion is guaranteed to succeed because it has been type checked by instanceof.

4. For each "key" field in the class, check whether the field in the parameter object matches the corresponding field in the current object.

Returns true if the above tests are all successful, otherwise returns false.

Among them, for the basic type field that is neither float nor double type, you can directly use the == operator for comparison, for the field of type float, use the Float.compare method, and for the field of type double, use the Double.compare method. For fields of reference type, call the equals method of the reference type to compare.

When a class's equals method completes, it should be clear: is it symmetric, transitive, consistent? Test code should be written to test.

Also bear in mind the caveat:

1. Always override the hashCode method when overriding the equals method.

2. Don't try to make the equals method too smart.

3. Do not change the parameter Object type to any other type. Because the parameter type of the equals method provided by the Object class is Object, if the parameter Object type is changed to another type, it becomes an overload of the equals method, not an override of the equals method. So you can add @Override annotation to avoid this kind of error.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325768336&siteId=291194637