Consider the following example:
public final class Person {
private final String firstName;
private final String lastName;
public Person(String firstName, String lastName) {
this.firstName = (firstName == null) ? "" : firstName;
this.lastName = (lastName == null) ? "" : lastName;
}
public boolean equals(String other) {
if (!(other instanceof Person)) {
return false;
}
Person p = (Person) other;
return firstName.equals(p.firstName) &&
lastName.equals(p.lastName);
}
public int hashcode() {
return firstName.hashCode() + 31 * lastName.hashCode();
}
}
This code is not going to behave as expected. The problem is that the equals
and hashcode
methods for Person
do not override the standard methods defined by Object
.
equals
method has the wrong signature. It should be declared as equals(Object)
not equals(String)
.hashcode
method has the wrong name. It should be hashCode()
(note the capital C).These mistakes mean that we have declared accidental overloads, and these won't be used if Person
is used in a polymorphic context.
However, there is a simple way to deal with this (from Java 5 onwards). Use the @Override
annotation whenever you intend your method to be an override:
public final class Person {
...
@Override
public boolean equals(String other) {
....
}
@Override
public hashcode() {
....
}
}
When we add an @Override
annotation to a method declaration, the compiler will check that the method does override (or implement) a method declared in a superclass or interface. So in the example above, the compiler will give us two compilation errors, which should be enough to alert us to the mistake.