Java › equals(), hashCode() & toString() Contracts
How would you use Lombok's @EqualsAndHashCode and @ToString annotations to eliminate equals()/hashCode()/toString() boilerplate, and what specific configuration options handle inheritance and field exclusion correctly?
AdvancedAnswer
Lombok's @EqualsAndHashCode (and separately @ToString) generate these methods at compile time based on the class's fields, with @EqualsAndHashCode.Exclude (or the older exclude attribute) letting you omit specific fields (like a mutable cache field, or a field that would create a circular toString()/equals() reference, such as a bidirectional parent-child relationship) from the generated implementation, and callSuper=true telling Lombok to incorporate the superclass's own equals()/hashCode()/toString() into the generated implementation, addressing the same inheritance concerns a manual implementation would need to handle explicitly.
@EqualsAndHashCode(callSuper = true)
@ToString(exclude = "password") // avoid leaking sensitive data into logs via toString()
public class User extends BaseEntity {
private String username;
private String password;
@EqualsAndHashCode.Exclude
private LocalDateTime lastAccessedCache; // mutable, excluded to avoid the mutable-field hashCode risk
}
// Lombok generates equals()/hashCode()/toString() automatically at compile time from the remaining fieldsReal-world example A User class annotated with Lombok's @ToString(exclude = "password") ensures the sensitive password field is never accidentally included when a User object is logged or printed for debugging, a safety measure easy to overlook when hand-writing toString() manually but simple to declare explicitly with Lombok's exclude option.