What are the important things to consider when implementing equals method?

Any equals implementation should satisfy these properties:
1. Reflexive.- For any reference value x, x.equals(x) returns true.
2. Symmetric.- For any reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
3. Transitive.- For any reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) must return true.
4. Consistent.- For any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, if no information used in equals is modified.
5. For any non-null reference value x, x.equals(null) should return false.

Our earlier implementation of equals method will not satisfy condition 5. It would throw an exception if an object of different class (other than Client) is used for comparison.

Let's now provide an implementation of equals which satisfy these properties:
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Client other = (Client) obj;
if (id != other.id)
return false;
return true;
}