[Effective Java] Please follow general conventions when overriding equals

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 Mapin keyit, then we can override the class Object.equalsmethod.

general convention

Overriding equalsmethods need to follow the following conventions:
1. Reflexivity
For any non- nullreference value x, x.equals(x)it must be true
2. Symmetry
For any non- nullreference value xsum , it must also return 3 yif 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 returntruex.equals(y)true

nullxyzx.equals(y)truey.equals(z)truex.equals(z)true

nullxyequalsx.equals(y)truefalse
nullxx.equals(null)false

how to write equalsmethod

  1. Use ==to judge whether the two objects are the same object, yes return true, otherwisefalse
  2. Use instanceofto determine whether the parameter has the correct type, if not returnfalse
  3. Cast the parameter to the correct type
  4. 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 (except floatsum double), directly use ==judgment
    2). For reference types, need to use equalsjudgment . If it is a custom class as an attribute, the custom class must also override equalsmethod
    3). For floatattributes, use Float.comparejudgment
    4). For doubleattributes, use Double.comparejudgment
    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 use Arrays.equalsmethod
    6). For the case where an attribute can be empty, it is necessary to point out that an exception is not thrown NullPointerException, 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

  1. Override equalsmethod, need to override hashCodemethod
  2. Don't write the wrong equalsmethod. The original method is public boolean equals(Object obj)that the parameter is a Objecttype, not a specified type.

Guess you like

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