Detailed explanation
For Integer values in Java, == and .equals() answer different questions. When both operands are references, == checks whether they refer to the same object, not whether they contain the same number. Integer overrides Object.equals() to compare numeric contents, provided the other object is also an Integer. Therefore, two distinct Integer objects holding 200 are unequal with == but equal with .equals(). This distinction matters because reference comparisons can accidentally appear correct in tests using small numbers.
Autoboxing converts an int into an Integer, normally through Integer.valueOf(int). That method always caches values from -128 through 127 and may cache additional values outside that range. Consequently, Integer a = 100, b = 100; makes a == b true because both variables receive the same cached instance. For Integer c = 200, d = 200;, c == d is normally false with the default cache, while c.equals(d) is true. However, describing 200 as definitely uncached is inaccurate: implementations or runtime settings may extend the cache. The cache reduces object allocation; it must not become a rule for value comparison.
Operand types also determine how == behaves. If one operand is an Integer and the other is an int, Java unboxes the Integer and compares primitive numeric values. For example, Integer x = 200; followed by x == 200 evaluates to true. If x is null, that comparison throws NullPointerException during unboxing. Calling x.equals(200) also throws when x is null, because an instance method needs a non-null receiver.
For nullable boxed values, prefer Objects.equals(a, b): it returns true when both are null, false when only one is null, and otherwise delegates to equals(). Also remember that Integer.valueOf(1).equals(Long.valueOf(1)) is false; Integer.equals() does not perform cross-type numeric conversion. Interviewers usually look for reference-versus-value semantics first, then cache behaviour, unboxing, and null handling. The practical rule is to compare boxed values with equals() or Objects.equals(), and use == for primitive values or intentional reference checks.
Key points to remember
- Integer == Integer compares object identity, not numeric contents.
- Integer.equals() compares values only when the other object is also an Integer.
- Integer.valueOf() caches -128 to 127 inclusive; caching beyond that range is possible.
- Integer == int unboxes the Integer and compares primitive values.
- Objects.equals(a, b) provides null-safe equality for boxed values.
Common mistakes candidates make
- Assuming == compares numeric values whenever both references are Integers.
- Claiming that two separately boxed values of 200 must always be different objects.
- Ignoring null-related exceptions from unboxing or calling .equals() on a null receiver.
Likely follow-up questions
Why does Integer x = 200; x == 200 evaluate to true?
The literal 200 is an int, so Java unboxes x and performs a primitive numeric comparison. The Integer cache is irrelevant to this comparison.
How should I compare two Integers that might be null?
Use java.util.Objects.equals(a, b). It handles both-null and one-null cases without unboxing, then uses value equality for non-null Integers.
Does Integer.valueOf(1).equals(Long.valueOf(1)) return true?
No, Integer.equals() requires the other object to be an Integer with the same value. To compare different numeric wrapper types numerically, choose an appropriate common numeric representation and account for nulls and possible precision loss.
Interview tip: Lead with identity versus value, demonstrate 100 and 200, then qualify the cache example and mention null-safe comparison.
