If the class needs to have the concept of "logical equality" (different from the concept of object equality), and there is no equals()
method that implements the same logic in its parent class, for example JDK8
, a custom class can be used Map
in key
it, then we can override the class Object.equals
method.
general convention
Overriding equals
methods need to follow the following conventions:
1. Reflexivity
For any non- null
reference value x
, x.equals(x)
it must be true
2. Symmetry
For any non- null
reference value x
sum , it must also return 3 y
if and only if it y.equals(x)
returns . Transitivity For any non- reference value , , , if it is , and is , then it must also be 4. Consistency For any non- reference value and , as long as the information used by the comparison operation in the object is not modified, multiple calls to the total will always return or 5. For any non- reference value , you must returntrue
x.equals(y)
true
null
x
y
z
x.equals(y)
true
y.equals(z)
true
x.equals(z)
true
null
x
y
equals
x.equals(y)
true
false
null
x
x.equals(null)
false
how to write equals
method
- Use
==
to judge whether the two objects are the same object, yes returntrue
, otherwisefalse
- Use
instanceof
to determine whether the parameter has the correct type, if not returnfalse
- Cast the parameter to the correct type
- Compare each meaningful attribute in the class with the corresponding attribute in the parameter, and return if they are the same
true
, otherwise
1). For basic type attributes (exceptfloat
sumdouble
), directly use==
judgment
2). For reference types, need to useequals
judgment . If it is a custom class as an attribute, the custom class must also overrideequals
method
3). Forfloat
attributes, useFloat.compare
judgment
4). Fordouble
attributes, useDouble.compare
judgment
5). For array attributes, each element needs to be based on the above principles Compare them one by one. If each element is very important, you can useArrays.equals
method
6). For the case where an attribute can be empty, it is necessary to point out that an exception is not thrownNullPointerException
, such as(field == o.field || (field != null && field.equals(o.field)))
Once you 've written it, it 's a good idea to test against the 5 conventions in the general convention .
Sample code:
public final class PhoneNumber {
private final short areaCode;
private final short prefix;
private final short lineNumber;
public PhoneNumber(int areaCode, int prefix, int lineNumber) {
rangeCheck(areaCode, 999, "area code");
rangeCheck(prefix, 999, "prefix");
rangeCheck(lineNumber, 9999, "line number");
this.areaCode = (short) areaCode;
this.prefix = (short) prefix;
this.lineNumber = (short) lineNumber;
}
private static void rangeCheck(int arg, int max, String name) {
if (arg < 0 || arg > max)
throw new IllegalArgumentException(name +": " + arg);
}
@Override public boolean equals(Object o) {
//==判断
if (o == this)
return true;
//instanceof判断
if (!(o instanceof PhoneNumber))
return false;
//各属性判断
PhoneNumber pn = (PhoneNumber)o;
return pn.lineNumber == lineNumber && pn.prefix == prefix && pn.areaCode == areaCode;
}
public int hashCode() {
//省略
}
}
important point
- Override
equals
method, need to overridehashCode
method - Don't write the wrong
equals
method. The original method ispublic boolean equals(Object obj)
that the parameter is aObject
type, not a specified type.