How to override equals method in Java
Solution 1:
//Written by K@stackoverflow
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person("Subash Adhikari", 28));
people.add(new Person("K", 28));
people.add(new Person("StackOverflow", 4));
people.add(new Person("Subash Adhikari", 28));
for (int i = 0; i < people.size() - 1; i++) {
for (int y = i + 1; y <= people.size() - 1; y++) {
boolean check = people.get(i).equals(people.get(y));
System.out.println("-- " + people.get(i).getName() + " - VS - " + people.get(y).getName());
System.out.println(check);
}
}
}
}
//written by K@stackoverflow
public class Person {
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj.getClass() != this.getClass()) {
return false;
}
final Person other = (Person) obj;
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
return false;
}
if (this.age != other.age) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + (this.name != null ? this.name.hashCode() : 0);
hash = 53 * hash + this.age;
return hash;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Output:
run:
-- Subash Adhikari - VS - K false
-- Subash Adhikari - VS - StackOverflow false
-- Subash Adhikari - VS - Subash Adhikari true
-- K - VS - StackOverflow false
-- K - VS - Subash Adhikari false
-- StackOverflow - VS - Subash Adhikari false
-- BUILD SUCCESSFUL (total time: 0 seconds)
Solution 2:
Introducing a new method signature that changes the parameter types is called overloading:
public boolean equals(People other){
Here People
is different than Object
.
When a method signature remains the identical to that of its superclass, it is called overriding and the @Override
annotation helps distinguish the two at compile-time:
@Override
public boolean equals(Object other){
Without seeing the actual declaration of age
, it is difficult to say why the error appears.
Solution 3:
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 haveObject
, notPeople
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 anint
(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.
Solution 4:
Item 10: Obey the general contract when overriding equals
According to Effective Java, Overriding the
equals
method seems simple, but there are many ways to get it wrong, and consequences can be dire. The easiest way to avoid problems is not to override theequals
method, in which case each instance of the class is equal only to itself. This is the right thing to do if any of the following conditions apply:
Each instance of the class is inherently unique. This is true for classes such as Thread that represent active entities rather than values. The equals implementation provided by Object has exactly the right behavior for these classes.
There is no need for the class to provide a “logical equality” test. For example, java.util.regex.Pattern could have overridden equals to check whether two Pattern instances represented exactly the same regular expression, but the designers didn’t think that clients would need or want this functionality. Under these circumstances, the equals implementation inherited from Object is ideal.
A superclass has already overridden equals, and the superclass behavior is appropriate for this class. For example, most Set implementations inherit their equals implementation from AbstractSet, List implementations from AbstractList, and Map implementations from AbstractMap.
The class is private or package-private, and you are certain that its equals method will never be invoked. If you are extremely risk-averse, you can override the equals method to ensure that it isn’t invoked accidentally:
The equals
method implements an equivalence relation. It has these properties:
Reflexive: For any non-null reference value
x
,x.equals(x)
must return true.Symmetric: For any non-null reference values
x
andy
,x.equals(y)
must return true if and only if y.equals(x) returns true.Transitive: For any non-null reference values
x
,y
,z
, ifx.equals(y)
returnstrue
andy.equals(z)
returnstrue
, thenx.equals(z)
must returntrue
.Consistent: For any non-null reference values
x
andy
, multiple invocations ofx.equals(y)
must consistently returntrue
or consistently returnfalse
, provided no information used in equals comparisons is modified.For any non-null reference value
x
,x.equals(null)
must returnfalse
.
Here’s a recipe for a high-quality equals method:
Use the
==
operator to check if the argument is a reference to this object. If so, return true. This is just a performance optimization but one that is worth doing if the comparison is potentially expensive.Use the
instanceof
operator to check if the argument has the correct type. If not, return false. Typically, the correct type is the class in which the method occurs. Occasionally, it is some interface implemented by this class. Use an interface if the class implements an interface that refines the equals contract to permit comparisons across classes that implement the interface. Collection interfaces such as Set, List, Map, and Map.Entry have this property.Cast the argument to the correct type. Because this cast was preceded by an instanceof test, it is guaranteed to succeed.
For each “significant” field in the class, check if that field of the argument matches the corresponding field of this object. If all these tests succeed, return true; otherwise, return false. If the type in Step 2 is an interface, you must access the argument’s fields via interface methods; if the type is a class, you may be able to access the fields directly, depending on their accessibility.
For primitive fields whose type is not
float
ordouble
, use the==
operator for comparisons; for object reference fields, call theequals
method recursively; forfloat
fields, use the staticFloat.compare(float, float)
method; and fordouble
fields, useDouble.compare(double, double)
. The special treatment of float and double fields is made necessary by the existence ofFloat.NaN
,-0.0f
and the analogous double values; While you could comparefloat
anddouble
fields with the static methodsFloat.equals
andDouble.equals
, this would entail autoboxing on every comparison, which would have poor performance. Forarray
fields, apply these guidelines to each element. If every element in an array field is significant, use one of theArrays.equals
methods.-
Some object reference fields may legitimately contain
null
. To avoid the possibility of aNullPointerException
, check such fields for equality using the static methodObjects.equals(Object, Object)
.// Class with a typical equals method public final class PhoneNumber { private final short areaCode, prefix, lineNum; public PhoneNumber(int areaCode, int prefix, int lineNum) { this.areaCode = rangeCheck(areaCode, 999, "area code"); this.prefix = rangeCheck(prefix, 999, "prefix"); this.lineNum = rangeCheck(lineNum, 9999, "line num"); } private static short rangeCheck(int val, int max, String arg) { if (val < 0 || val > max) throw new IllegalArgumentException(arg + ": " + val); return (short) val; } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof PhoneNumber)) return false; PhoneNumber pn = (PhoneNumber)o; return pn.lineNum == lineNum && pn.prefix == prefix && pn.areaCode == areaCode; } ... // Remainder omitted }