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 ove
When comparing objects in Java, you make a semantic check, comparing the type and identifying state of the objects to:
null
Rules:
a.equals(b) == b.equals(a)
equals()
always yields true
or false
, but never a NullpointerException
, ClassCastException
or any other throwableComparison:
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)
. 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 instance type
* @return true when equals, false otherwise
*/
public static 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);
}