Understanding Equality
Primitives: == Is Always Value Comparison
For primitive types (int, double, boolean, char, etc.), == compares the actual values. There are no objects involved.
javaint a = 5;
int b = 5;
System.out.println(a == b); // true
double x = 3.14;
double y = 3.14;
System.out.println(x == y); // trueObjects: == Compares References
For object types, == checks whether two variables point to the same object in memory (same reference), not whether their contents are equal.
javaStringBuilder sb1 = new StringBuilder("hello");
StringBuilder sb2 = new StringBuilder("hello");
System.out.println(sb1 == sb2); // false — different objects
System.out.println(sb1.equals(sb2)); // false — StringBuilder doesn't override equals!javaStringBuilder sb3 = sb1;
System.out.println(sb1 == sb3); // true — same referenceString Pool and ==
String literals are stored in the string pool, so two literals with the same content share the same reference.
javaString s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
System.out.println(s1 == s2); // true — both from pool
System.out.println(s1 == s3); // false — s3 is a new heap object
System.out.println(s1.equals(s3)); // true — same contentnew String(...) always creates a fresh object on the heap, bypassing the pool. You can call intern() to place it in the pool and return the pooled reference.
javaString s4 = new String("hello").intern();
System.out.println(s1 == s4); // true — intern() returns the pooled referenceThe equals() Method
Object.equals() defaults to reference comparison (==). Classes that care about content equality override it. The standard Java types you should know:
| Class | equals() behavior |
|---|---|
String |
Compares character content |
Integer, Long, etc. |
Compares numeric value |
LocalDate, LocalTime |
Compares field values |
StringBuilder |
Does not override — uses reference |
| Custom classes | Depends on whether you override |
javaString a = new String("Java");
String b = new String("Java");
System.out.println(a.equals(b)); // true
Integer x = new Integer(42); // deprecated but valid
Integer y = new Integer(42);
System.out.println(x.equals(y)); // trueThe equals() Contract
A correct equals() implementation must satisfy:
| Property | Meaning |
|---|---|
| Reflexive | x.equals(x) is always true |
| Symmetric | x.equals(y) implies y.equals(x) |
| Transitive | x.equals(y) and y.equals(z) implies x.equals(z) |
| Consistent | Same result on repeated calls with unchanged objects |
| Null-safe | x.equals(null) is always false |
Calling equals() on null causes a NullPointerException:
javaString s = null;
s.equals("hello"); // NullPointerException!
"hello".equals(s); // safe — returns falseObjects.equals() — Null-Safe Comparison
java.util.Objects.equals(a, b) handles null safely without throwing:
javaimport java.util.Objects;
String a = null;
String b = "hello";
System.out.println(Objects.equals(a, b)); // false
System.out.println(Objects.equals(null, null)); // true
System.out.println(Objects.equals("hi", "hi")); // trueThe implementation is: (a == b) || (a != null && a.equals(b)). Prefer Objects.equals() when either argument might be null.
Integer Caching and ==
Java caches Integer objects for values from -128 to 127. This creates a subtle trap:
javaInteger a = 100;
Integer b = 100;
System.out.println(a == b); // true — cached
Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false — outside cache rangeThis behavior applies to autoboxed Integer, Long, Short, Byte, Character (0–127), and Boolean. Always use equals() when comparing wrapper objects.
Summary Table
| Scenario | Use == |
Use equals() |
|---|---|---|
| Primitive values | Yes | N/A |
| Same object reference? | Yes | — |
| String content | No (pool exception aside) | Yes |
Wrapper content (Integer, etc.) |
No | Yes |
| Null-safe content check | — | Objects.equals() |
Exam Tips
==on objects is a reference check, not a content check.- String literals with the same text share a pool reference and will satisfy
==. StringBuilderdoes not overrideequals()— twoStringBuilderinstances with equal content returnfalsewithequals().- Always use
equals()(orObjects.equals()) for content comparison of objects. - Put the known non-null value on the left of
equals()to avoidNullPointerException:"expected".equals(variable).