Skip to main content

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

OperatorNameDescriptionExampleResult
==Equaltrue if both values are equal5 == 5true
!=Not equaltrue if the values differ5 != 3true
>Greater thantrue if left is greater than right5 > 3true
<Less thantrue if left is less than right3 < 5true
>=Greater than or equaltrue if left is greater than or equal to right5 >= 5true
<=Less than or equaltrue if left is less than or equal to right3 <= 5true
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
}
}
boolean type cannot use relational operators

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)
}
}
Always use .equals() for string comparison

Never 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 ValueMeaning
Negative(< 0)Calling object is less than the argument
0Both 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
}
}
Only use isNaN() to check for NaN

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 TargetMethodNotes
Primitives (int, double, etc.)Use ==, !=, >, < directlyNone
String.equals(), .equalsIgnoreCase()Never use ==
Objects that may be nullObjects.equals(a, b)Prevents NPE
Order comparison.compareTo()Returns negative/0/positive
NaNDouble.isNaN(), Float.isNaN()Cannot compare with ==