Understanding Objects.equals and Common Pitfalls in Java Equality Checks
This article explains how Java's Objects.equals works, compares it with the == operator and the equals method of primitive wrappers, demonstrates typical null‑pointer and type‑mismatch pitfalls, and provides practical code examples and solutions for reliable value comparison.
When reviewing code, the author discovered that using Objects.equals to compare a Long field with an int literal returned false instead of the expected true , prompting an investigation into Java equality semantics.
The scenario involves checking whether the currently logged‑in user is a system administrator whose ID is the constant 888 . The naive implementation uses Objects.equals(userInfo.getId(), 888) , but the id field is a Long while 888 is an int , causing a type mismatch.
UserInfo userInfo = CurrentUser.getUserInfo();
if (Objects.isNull(userInfo)) {
log.info("请先登录");
return;
}
if (Objects.equals(userInfo.getId(), 888)) {
sendEmail(userInfo);
}The UserInfo class defines Long id , so Objects.equals ends up calling Long.equals(Object) , which returns false when the argument is not a Long .
The article then reviews various ways to test equality in Java:
Using the == operator
Works for primitive types and for reference comparison of objects; however, comparing wrapper objects may yield false because it checks reference identity.
int a = 1;
int b = 1;
Integer d1 = new Integer(1);
Integer d2 = new Integer(1);
System.out.println(a == b); // true
System.out.println(d1 == d2); // falseInteger values between -128 and 127 are cached, so Integer d3 = 1; Integer d4 = 1; compare equal with == , but larger values do not.
Using equals
The default Object.equals checks reference equality. Classes like String override it to compare actual content.
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj instanceof String) {
String another = (String) obj;
// compare character arrays
}
return false;
}Calling e.equals(f) on a null reference throws NullPointerException ; a safe wrapper method can be used to avoid this.
private static boolean equals(String e, String f) {
if (e == null) return f == null;
return e.equals(f);
}Objects.equals
The utility method Objects.equals(a, b) safely handles null values: it returns (a == b) || (a != null && a.equals(b)) .
System.out.println(Objects.equals(a, b)); // true if both non‑null and equalHowever, a hidden pitfall appears when the two arguments have different wrapper types. For example, Integer a = 1; long b = 1L; yields false because Integer.equals(Object) returns false for a Long argument, and vice‑versa.
Integer a = 1;
long b = 1L;
System.out.println(Objects.equals(a, b)); // false
System.out.println(a == b); // true (auto‑unboxing)To make the comparison work, cast one operand to the other's primitive type or use == when appropriate.
System.out.println(Objects.equals(a, (int) b)); // true
System.out.println(Objects.equals(b, (long) a)); // trueThe article lists common scenarios where mismatched types cause bugs: comparing Long with Integer for user IDs, Byte with Integer for status codes, and Double with Integer for zero‑amount checks.
In summary, while Objects.equals protects against NullPointerException , developers must ensure the two arguments are of compatible types; otherwise, the method may incorrectly report inequality.
IT Services Circle
Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.