Ch 3.4 Comparison Operators
Comparison operators compare two operands and return true or false. They are used together with conditionals (if, while, for) and are a core element for controlling program flow.
1. All 6 Comparison Operators
| Operator | Name | Description | Example | Result |
|---|---|---|---|---|
== | Equal | true if both values are equal | 5 == 5 | true |
!= | Not equal | true if the values differ | 5 != 3 | true |
> | Greater than | true if left is greater than right | 5 > 3 | true |
< | Less than | true if left is less than right | 3 < 5 | true |
>= | Greater than or equal | true if left is greater than or equal to right | 5 >= 5 | true |
<= | Less than or equal | true if left is less than or equal to right | 3 <= 5 | true |
public class ComparisonBasic {
public static void main(String[] args) {
int a = 10, b = 5, c = 10;
System.out.println("a == b : " + (a == b)); // false
System.out.println("a == c : " + (a == c)); // true
System.out.println("a != b : " + (a != b)); // true
System.out.println("a > b : " + (a > b)); // true
System.out.println("a < b : " + (a < b)); // false
System.out.println("a >= c : " + (a >= c)); // true
System.out.println("b <= c : " + (b <= c)); // true
}
}
The boolean type can only use == and !=; >, <, >=, <= are not allowed.
boolean flag = true;
// System.out.println(flag > false); // Compile error!
System.out.println(flag == true); // true (valid, but using flag directly is more idiomatic)
2. Primitive Comparison: Direct Value Comparison
When == is used on primitives (int, long, double, boolean, char), it directly compares the values.
public class PrimitiveComparison {
public static void main(String[] args) {
int x = 100;
int y = 100;
System.out.println(x == y); // true (same value)
double d1 = 3.14;
double d2 = 3.14;
System.out.println(d1 == d2); // true
char c1 = 'A';
char c2 = 65; // Unicode value of 'A'
System.out.println(c1 == c2); // true (char is internally a number)
boolean b1 = true;
boolean b2 = true;
System.out.println(b1 == b2); // true
}
}
3. Reference Type Comparison: == Compares Addresses
When == is used on objects (reference types), it compares the memory address (reference value), not the content. Therefore, even if two objects have the same content, false is returned if they are different objects.
public class ReferenceComparison {
public static void main(String[] args) {
// Two arrays created with new: same content but different objects
int[] arr1 = {1, 2, 3};
int[] arr2 = {1, 2, 3};
int[] arr3 = arr1; // Copy the reference value of arr1
System.out.println(arr1 == arr2); // false (different objects, different addresses)
System.out.println(arr1 == arr3); // true (pointing to the same object)
// Use Arrays.equals() to compare array content
System.out.println(java.util.Arrays.equals(arr1, arr2)); // true (content comparison)
}
}
4. String Comparison Pitfall: String Pool
Due to Java's special memory management (String Pool) for String, using == for comparison can produce unexpected results.
public class StringComparison {
public static void main(String[] args) {
// Literal method: reused from String Pool
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true (same Pool object)
System.out.println(s1.equals(s2)); // true
// new keyword: always creates a new object (outside the Pool)
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s3 == s4); // false (different objects)
System.out.println(s3.equals(s4)); // true (same content)
// Comparing literal and new
System.out.println(s1 == s3); // false (Pool object vs heap object)
System.out.println(s1.equals(s3)); // true
// intern(): registers in Pool to allow == comparison (rarely used)
String s5 = s3.intern();
System.out.println(s1 == s5); // true (after intern, references Pool)
}
}
.equals() for string comparisonNever use == when comparing String. With string literals it may accidentally return true, but strings created with new String() or returned from methods will always return false.
Always use .equals()!
// Bad example
if (userInput == "yes") { ... }
// Good example
if ("yes".equals(userInput)) { ... } // null-safe (constant on left)
if (userInput.equals("yes")) { ... } // NullPointerException if userInput is null
5. The equals() Method in Depth
Every Java class inherits equals() from the Object class. The default implementation is the same as == (address comparison), but many classes like String, Integer, List override it for content comparison.
public class EqualsMethod {
public static void main(String[] args) {
// String.equals(): content comparison (overridden)
String s1 = new String("Java");
String s2 = new String("Java");
System.out.println(s1.equals(s2)); // true
// Integer.equals(): value comparison (overridden)
Integer i1 = new Integer(100);
Integer i2 = new Integer(100);
System.out.println(i1.equals(i2)); // true
// Integer caching note: values in range -128 ~ 127 are cached
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true (cached object)
Integer c = 128;
Integer d = 128;
System.out.println(c == d); // false (exceeds cache range)
System.out.println(c.equals(d)); // true
// Case-insensitive comparison
String str = "Hello";
System.out.println(str.equals("hello")); // false
System.out.println(str.equalsIgnoreCase("hello")); // true
}
}
6. Objects.equals(): Null-Safe Comparison
String.equals() throws a NullPointerException if the left-hand object is null. Using java.util.Objects.equals() safely handles null.
import java.util.Objects;
public class NullSafeComparison {
public static void main(String[] args) {
String name = null;
// Dangerous: NullPointerException
// System.out.println(name.equals("Alice")); // NPE!
// Safe method 1: null check first
System.out.println(name != null && name.equals("Alice")); // false
// Safe method 2: constant on left (null doesn't have equals)
System.out.println("Alice".equals(name)); // false (no NPE)
// Safe method 3: Objects.equals() (null handling built-in)
System.out.println(Objects.equals(name, "Alice")); // false
System.out.println(Objects.equals(null, null)); // true
System.out.println(Objects.equals("Alice", null)); // false
// How Objects.equals works internally:
// (a == b) || (a != null && a.equals(b))
}
}
7. The compareTo() Method
== and != alone cannot tell you "how much greater or lesser" something is. The compareTo() method of the Comparable interface compares the order of two objects and returns an integer.
| Return Value | Meaning |
|---|---|
| Negative(< 0) | Calling object is less than the argument |
| 0 | Both objects are equal |
| Positive(> 0) | Calling object is greater than the argument |
public class CompareToExample {
public static void main(String[] args) {
// String.compareTo(): lexicographic (alphabetical) order comparison
String apple = "apple";
String banana = "banana";
String apple2 = "apple";
System.out.println(apple.compareTo(banana)); // negative (a < b alphabetically)
System.out.println(banana.compareTo(apple)); // positive
System.out.println(apple.compareTo(apple2)); // 0 (equal)
// Integer.compareTo(): numeric size comparison
Integer n1 = 10;
Integer n2 = 20;
System.out.println(n1.compareTo(n2)); // -1 (10 < 20)
System.out.println(n2.compareTo(n1)); // 1 (20 > 10)
System.out.println(n1.compareTo(10)); // 0 (equal)
// Main use of compareTo: sorting
String[] fruits = {"banana", "cherry", "apple"};
java.util.Arrays.sort(fruits); // Sorts based on compareTo
System.out.println(java.util.Arrays.toString(fruits)); // [apple, banana, cherry]
}
}
8. NaN Comparison Caution
The special value NaN (Not a Number) of float/double is not equal to even itself. It is the only value that returns false in all comparison operations.
public class NaNComparison {
public static void main(String[] args) {
double nan = Double.NaN;
System.out.println(nan == nan); // false (NaN is not equal to itself!)
System.out.println(nan != nan); // true
System.out.println(nan > 0); // false
System.out.println(nan < 0); // false
System.out.println(nan == 0); // false
// Always use isNaN() to check for NaN
System.out.println(Double.isNaN(nan)); // true
System.out.println(Float.isNaN(Float.NaN)); // true
// Cases where NaN arises
double result1 = 0.0 / 0.0;
double result2 = Math.sqrt(-1);
System.out.println(Double.isNaN(result1)); // true
System.out.println(Double.isNaN(result2)); // true
}
}
The fact that nan == nan is false is an intentional design of Java (IEEE 754 standard). Always use Double.isNaN() or Float.isNaN().
9. Practical Example: Grade Checker Program
import java.util.Scanner;
public class GradeChecker {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter student name: ");
String name = scanner.nextLine();
System.out.print("Enter score (0~100): ");
int score = scanner.nextInt();
// Validation: check score range
if (score < 0 || score > 100) {
System.out.println("Error: Score must be between 0 and 100.");
return;
}
// Grade determination
String grade;
String comment;
if (score >= 90) {
grade = "A";
comment = "Excellent";
} else if (score >= 80) {
grade = "B";
comment = "Good";
} else if (score >= 70) {
grade = "C";
comment = "Average";
} else if (score >= 60) {
grade = "D";
comment = "Below average";
} else {
grade = "F";
comment = "Fail";
}
// Pass/fail (60 or above)
boolean passed = score >= 60;
// Honors (95 or above)
boolean honor = score >= 95;
// Output
System.out.println();
System.out.println("====== Grade Result ======");
System.out.println("Name: " + name);
System.out.println("Score: " + score);
System.out.println("Grade: " + grade + " (" + comment + ")");
System.out.println("Result: " + (passed ? "Pass" : "Fail"));
if (honor) {
System.out.println("Congratulations! You qualify for honors.");
}
// Compare with passing score using subtraction
int passingScore = 60;
int diff = score - passingScore;
if (passed) {
System.out.println("You scored " + diff + " points above the passing score.");
} else {
System.out.println("You need " + Math.abs(diff) + " more points to pass.");
}
scanner.close();
}
}
Sample output (score 87):
Enter student name: Alice
Enter score (0~100): 87
====== Grade Result ======
Name: Alice
Score: 87
Grade: B (Good)
Result: Pass
You scored 27 points above the passing score.
10. Key Summary
| Comparison Target | Method | Notes |
|---|---|---|
| Primitives (int, double, etc.) | Use ==, !=, >, < directly | None |
| String | .equals(), .equalsIgnoreCase() | Never use == |
| Objects that may be null | Objects.equals(a, b) | Prevents NPE |
| Order comparison | .compareTo() | Returns negative/0/positive |
| NaN | Double.isNaN(), Float.isNaN() | Cannot compare with == |