How to override equals method in Java

2018-12-31 08:34发布

I am trying to override equals method in Java. I have a class People which basically has 2 data fields name and age. Now I want to override equals method so that I can check between 2 People objects.

My code is as follows

public boolean equals(People other){
    boolean result;
    if((other == null) || (getClass() != other.getClass())){
        result = false;
    } // end if
    else{
        People otherPeople = (People)other;
        result = name.equals(other.name) &&  age.equals(other.age);
    } // end else

    return result;
} // end equals

But when I write age.equals(other.age) it gives me error as equals method can only compare String and age is Integer.

Solution

I used == operator as suggested and my problem is solved.

9条回答
与君花间醉酒
2楼-- · 2018-12-31 09:08

I'm not sure of the details as you haven't posted the whole code, but:

  • remember to override hashCode() as well
  • the equals method should have Object, not People as its argument type. At the moment you are overloading, not overriding, the equals method, which probably isn't what you want, especially given that you check its type later.
  • you can use instanceof to check it is a People object e.g. if (!(other instanceof People)) { result = false;}
  • equals is used for all objects, but not primitives. I think you mean age is an int (primitive), in which case just use ==. Note that an Integer (with a capital 'I') is an Object which should be compared with equals.

See What issues should be considered when overriding equals and hashCode in Java? for more details.

查看更多
梦醉为红颜
3楼-- · 2018-12-31 09:12

The method equals defines a method parameter of type Object and its return type is boolean.

Don’t change the name of the method, its return type, or the type of method parameter

when you define (override) this method in your class to compare two objects.

public boolean equals(Object anObject) {
...
}
查看更多
无与为乐者.
4楼-- · 2018-12-31 09:19

When comparing objects in Java, you make a semantic check, comparing the type and identifying state of the objects to:

  • itself (same instance)
  • itself (clone, or reconstructed copy)
  • other objects of different types
  • other objects of the same type
  • null

Rules:

  • Symmetry: a.equals(b) == b.equals(a)
  • equals() always yields true or false, but never a NullpointerException, ClassCastException or any other throwable

Comparison:

  • Type check: both instances need to be of the same type, meaning you have to compare the actual classes for equality. This is often not correctly implemented, when developers use instanceof for type comparison (which only works as long as there are no subclasses, and violates the symmetry rule when A extends B -> a instanceof b != b instanceof a).
  • Semantic check of identifying state: Make sure you understand by which state the instances are identified. Persons may be identified by their social security number, but not by hair color (can be dyed), name (can be changed) or age (changes all the time). Only with value objects should you compare the full state (all non-transient fields), otherwise check only what identifies the instance.

For your Person class:

public boolean equals(Object obj) {

    // same instance
    if (obj == this) {
        return true;
    }
    // null
    if (obj == null) {
        return false;
    }
    // type
    if (!getClass().equals(obj.getClass())) {
        return false;
    }
    // cast and compare state
    Person other = (Person) obj;
    return Objects.equals(name, other.name) && Objects.equals(age, other.age);
}

Reusable, generic utility class:

public final class Equals {

    private Equals() {
        // private constructor, no instances allowed
    }

    /**
     * Convenience equals implementation, does the object equality, null and type checking, and comparison of the identifying state
     *
     * @param instance       object instance (where the equals() is implemented)
     * @param other          other instance to compare to
     * @param stateAccessors stateAccessors for state to compare, optional
     * @param <T>            instance type
     * @return true when equals, false otherwise
     */
    public static <T> boolean as(T instance, Object other, Function<? super T, Object>... stateAccessors) {
        if (instance == null) {
            return other == null;
        }
        if (instance == other) {
            return true;
        }
        if (other == null) {
            return false;
        }
        if (!instance.getClass().equals(other.getClass())) {
            return false;
        }
        if (stateAccessors == null) {
            return true;
        }
        return Stream.of(stateAccessors).allMatch(s -> Objects.equals(s.apply(instance), s.apply((T) other)));
    }
}

For your Person class, using this utility class:

public boolean equals(Object obj) {
    return Equals.as(this, obj, t -> t.name, t -> t.age);
}
查看更多
登录 后发表回答