All 15 equals(), hashCode() & toString() Contracts questions
More in equals(), hashCode() & toString() Contracts
Advertisement
Back to results for “Generics”
Java › equals(), hashCode() & toString() Contracts

What is the relationship between equals() and the == operator when comparing primitive types versus reference types, and how does this affect comparing boxed wrapper types like Integer?

Intermediate

Answer

== between primitives compares actual values directly (numeric or boolean equality); == between reference types (including boxed wrapper types like Integer) compares object identity (whether both references point to the same object instance) rather than logical value equality -- this creates a notorious pitfall with boxed types due to Integer's internal caching of small values (-128 to 127 by default): == happens to "work" correctly for cached small values purely by coincidence (both variables reference the same cached instance) but silently breaks for larger values outside that cache range, making == fundamentally unreliable for comparing boxed wrapper type values and .equals() (or unboxing to a primitive first) the only genuinely correct approach.
Integer a = 100, b = 100;
System.out.println(a == b);  // true, coincidentally -- both within the cached range (-128 to 127)

Integer c = 200, d = 200;
System.out.println(c == d);  // false! Outside the cache range, two genuinely distinct Integer objects

System.out.println(c.equals(d));  // true, correctly compares actual values regardless of caching
Real-world example A subtle production bug where a numeric comparison worked correctly in testing (using small sample values under 128) but failed unpredictably in production (with larger real-world values) is traced to using == instead of .equals() to compare two Integer objects, exploiting a misunderstanding of Integer's internal small-value caching behavior.

Common follow-ups: Why does Java cache small Integer values in the first place, and can this caching range be configured?;What's the safest general practice for comparing boxed numeric types to avoid this pitfall entirely?