Let's say I have a simple class that represents a game tile, called Tile
:
public class Tile {
public final int x;
public final int y;
public final int plane;
public Tile(int x, int y, int plane) {
this.x = x;
this.y = y;
this.plane = plane;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (obj instanceof Tile) {
Tile other = (Tile) obj;
return other.x == x && other.y == y && other.plane == plane;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(x, y, plane);
}
}
Being a responsible citizen, I implemented the hashCode
method to make sure hash codes of equivalent objects are equal, per contract of equals
. Then I was thinking, for any two Tile
objects that have the same values for the x
, y
, and plane
fields, the hash codes - as they should - will be equal. So why not just use that to check if objects are equivalent, rather than individually comparing the values of the fields?
More explicitly, why not replace:
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (obj instanceof Tile) {
Tile other = (Tile) obj;
return other.x == x && other.y == y && other.plane == plane;
}
return false;
}
with simply:
@Override
public boolean equals(Object obj) {
return obj == this || obj != null && obj.hashCode() == hashCode();
}
Part of me feels that this is bad practice. This almost feels like circular reasoning. However, I cannot think of a valid, practical reason as to why this would be a bad practice.
In short: is it appropriate to use the result of hashCode
to determine the result of equals
?