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;
}
}