Avoid Using @Nonnull in equals Method Parameters
What is it?
This practice advises against using @Nonnull in the parameter of the overridden equals method, as the contract of equals requires it to properly handle null parameters.
Why apply it?
The equals method should be able to process a null argument by returning false, as specified in the java.lang.Object documentation. Using @Nonnull contradicts this requirement and can lead to unexpected behavior.
How to fix it?
Remove the @Nonnull annotation from the equals method parameter and handle null appropriately within the method's implementation.
Examples
Example 1:
Negative
The negative example shows a noncompliant equals method with a @Nonnull parameter, violating the method's contract.
import javax.annotation.Nonnull;
public class Car {
private String model;
public Car(String model) {
this.model = model;
}
@Override
public boolean equals(@Nonnull Object obj) { // Noncompliant
if (this == obj) {
return true;
}
if (getClass() != obj.getClass()) {
return false;
}
Car car = (Car) obj;
return model != null ? model.equals(car.model) : car.model == null;
}
@Override
public int hashCode() {
// Simplified hash code implementation
return model != null ? model.hashCode() : 0;
}
}
Example 2:
Positive
The positive example shows a compliant equals method that checks for null without using @Nonnull.
public class Car {
private String model;
public Car(String model) {
this.model = model;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Car car = (Car) obj;
return model != null ? model.equals(car.model) : car.model == null;
}
@Override
public int hashCode() {
// Simplified hash code implementation
return model != null ? model.hashCode() : 0;
}
}
Negative
This negative example incorrectly uses @Nonnull in the equals method parameter, which should accept null.
import javax.annotation.Nonnull;
public class Book {
private String title;
public Book(String title) {
this.title = title;
}
@Override
public boolean equals(@Nonnull Object obj) { // Noncompliant
if (this == obj) {
return true;
}
if (getClass() != obj.getClass()) {
return false;
}
Book book = (Book) obj;
return title != null ? title.equals(book.title) : book.title == null;
}
@Override
public int hashCode() {
return title != null ? title.hashCode() : 0;
}
}
Example 3:
Positive
This positive example correctly handles null by checking for it at the beginning of the equals method.
public class Book {
private String title;
public Book(String title) {
this.title = title;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Book book = (Book) obj;
return title != null ? title.equals(book.title) : book.title == null;
}
@Override
public int hashCode() {
return title != null ? title.hashCode() : 0;
}
}