Fundamentals 16 min read

Why Does Objects.equals Sometimes Return False? Uncover Java’s Equality Pitfalls

This article explains why Java's Objects.equals can yield unexpected false results, compares different equality‑checking methods, shows how type mismatches and null values cause pitfalls, and provides practical code examples and solutions for safe object comparison.

macrozheng
macrozheng
macrozheng
Why Does Objects.equals Sometimes Return False? Uncover Java’s Equality Pitfalls

Preface

While reviewing a colleague's code I discovered that using Objects.equals to compare two values returned a result different from the expectation, which sparked my interest.

I originally expected the comparison to return true, but it actually returned false.

Having encountered similar pitfalls with Objects.equals before, I felt it was necessary to record this issue and share it.

1. The Scene

Assume a requirement: if the currently logged‑in user is the designated system administrator, send an email. The admin has no special flag; its user id is 888 in development, testing, and production.

The implementation looks straightforward:

UserInfo userInfo = CurrentUser.getUserInfo();

if (Objects.isNull(userInfo)) {
    log.info("Please log in first");
    return;
}

if (Objects.equals(userInfo.getId(), 888)) {
    sendEmail(userInfo);
}

After logging in with the admin account (id=888) and performing the operation, no email was received.

The UserInfo class is defined as:

@Data
public class UserInfo {
    private Long id;
    private String name;
    private Integer age;
    private String address;
}

The problem lies in the type mismatch: the id field is Long, while the literal 888 is an int. Because the two types differ, Objects.equals returns false.

2. Methods for Equality Comparison

2.1 Using the == Operator

The fastest way to compare primitive values is the == operator.

int a = 1;
int b = 1;
byte c = 1;
Integer d1 = new Integer(1);
Integer d2 = new Integer(1);
System.out.println(a == b); // true
System.out.println(a == c); // true
System.out.println(a == d1); // true
System.out.println(d2 == a); // true
System.out.println(d1 == d2); // false

For primitive types the == operator compares values directly. For wrapper classes, == compares object references, which can yield false even when the values are equal.

When an Integer is compared with an int , automatic unboxing occurs, so the values are compared.

Two distinct Integer objects (e.g., created with new) are not guaranteed to be == even if they hold the same value.

Comparing two Integer objects with == checks whether they reference the same memory address.

Integer values between -128 and 127 are cached, so Integer d3 = 1; Integer d4 = 1; results in d3 == d4 being true, while values outside that range (e.g., 128) are not cached, making d5 == d6 false.

2.2 Using the equals Method

The == operator cannot compare the internal data of two distinct objects. For such cases, the equals method should be used.

String g = new String("abc");
String h = new String("abc");
System.out.println(g == h); // false

Although the references differ, the string contents are identical. The String class overrides equals to compare character arrays element‑by‑element, returning true when the contents match.

String e = "abc";
String f = "abc";
System.out.println(e.equals(f)); // true

3. NullPointerException

Both == and equals can throw a NullPointerException when one operand is null. For example:

int a = 1;
Integer c = null;
System.out.println(a == c); // NullPointerException

Similarly, invoking e.equals(f) when e is null throws an exception.

The solution is to perform a null check before calling equals, or use a utility method such as:

private static boolean equals(String e, String f) {
    if (e == null) {
        return f == null;
    }
    return e.equals(f);
}

4. Purpose of Objects.equals

The Objects class in java.util provides helper methods, among which Objects.equals(Object a, Object b) is widely used.

public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}

This method first checks reference equality, then null‑safety, and finally delegates to a.equals(b). It avoids NullPointerExceptions and is convenient for safe comparisons.

5. Pitfalls of Objects.equals

A hidden pitfall appears when the two arguments have different wrapper types. Example:

Integer a = 1;
long b = 1L;
System.out.println(Objects.equals(a, b)); // false

Even though the numeric values are equal, Objects.equals returns false because Integer.equals only returns true when the argument is also an Integer. The same behavior exists for Long.equals, Byte.equals, Short.equals, Double.equals, Float.equals, Boolean.equals, and Character.equals.

When using Objects.equals , ensure that both parameters are of the same type; otherwise equal numeric values may still be considered unequal.

To fix the issue, cast one argument to the other's type before comparison, or simply use the == operator for primitive values.

System.out.println(Objects.equals(a, (int) b)); // true
System.out.println(Objects.equals(b, (long) a)); // true

In summary, while Objects.equals is a handy null‑safe comparator, developers must be aware of type‑mismatch pitfalls, especially when dealing with primitive wrapper classes.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javanullpointerexceptionPitfallsequalityObjects.equals
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.