Comparison Operators
In short: Operators that compare two values and return a boolean (true/false): == != < > <= >=.
In more detail: Important trap in Java: == compares the reference for objects (e.g. String), not the content — two strings that are equal in content can still return false with == if they’re different objects in memory. For comparing the content of objects, .equals() should be used instead.
In Depth
String a = "hello";
String b = "hello";
String c = new String("hello");
System.out.println(a == b); // true - Java automatically "interns" identical string literals
System.out.println(a == c); // false - c is a separate object on the heap
System.out.println(a.equals(c)); // true - content comparison, independent of object identity
Integer x = 127, y = 127;
Integer p = 200, q = 200;
System.out.println(x == y); // true - Integer cache for -128..127
System.out.println(p == q); // false! Outside the cache they're different objectsThe Integer cache case is especially tricky: Java automatically caches Integer objects for small values (-128 to 127) for performance reasons, which makes == comparisons “work” by coincidence in this range but not outside it — a classic bug that goes undetected in tests with small numbers and only shows up in production with larger values. Rule of thumb with no exceptions: for primitive types (int, double, boolean, …), == is correct and the only possible comparison; for objects (String, Integer, your own classes, …), always use .equals(), never ==.
Relational operators for different types
< > <= >= in Java only work on primitive numeric types (int, double, char, …), NOT directly on objects like String — "apple" < "banana" simply doesn’t compile. For lexicographic comparison of strings, there’s compareTo() instead:
String a = "apple", b = "banana";
System.out.println(a.compareTo(b)); // negative, since "apple" comes alphabetically before "banana"
System.out.println(a.compareTo(a)); // 0 - identicalThe sign of the return value counts, not the exact numeric value — negative means “comes before”, positive “comes after”, 0 means “equal”. This compareTo() pattern runs throughout all of Java: the Comparable interface (for a class’s “natural” sort order) and Comparator (for custom sort orders) both build exactly on this.
Overriding equals() yourself
For your own classes, .equals() without a custom implementation by default returns the same result as == (reference comparison), since Object.equals() does exactly that. For a true content comparison, equals() (and, for consistency, also always hashCode()) has to be overridden:
class Point {
int x, y;
@Override
public boolean equals(Object o) {
if (!(o instanceof Point p)) return false;
return x == p.x && y == p.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}If equals() is overridden but hashCode() is forgotten (or vice versa), HashSet/HashMap behave inconsistently — two objects that are equal according to equals() can then still be treated as “different” because they have different hash codes.
See also: Operators, Logical Operators, if Statement