Concepts / Boolean Operators in Java

Boolean Operators in Java

Java's relational operators are ==, !=, <, >, <=, and >=.

  • Programming

Why a Comparison Can Surprise You

Comparisons are the foundation of decision making in a program. An if statement asks a question, and the answer decides which code runs. In Java, the question is usually written with a relational operator such as < or ==, or with a boolean operator such as && that combines several questions. Most comparisons behave the way you would expect, but some do not. Two cases need special care: String objects and the special value Double.NaN. This article builds the rules step by step so you can predict the result of a comparison before you run the code.

What do you think happens?

Two String variables hold the same text. What do you think a == comparison returns, and what does equals() return?

  • == is true and equals() is true

  • == is false and equals() is true

  • == is true and equals() is false

  • == is false and equals() is false

Reveal answer
Answer:

== is false and equals() is true

The == operator checks the storage location of the objects, not their text. Two separate String objects with identical text are different objects, so == returns false. equals() compares the contents, so it returns true. This is explored in detail in the String section below.

The Six Relational Operators

Java's relational operators are ==, !=, <, >, <=, and >=. Each one compares two values and produces a boolean result, true or false. Together they cover equality, inequality, less than, greater than, less than or equal, and greater than or equal. Because each comparison produces a boolean value, you can use it directly as the condition of an if statement, store it in a boolean variable, or combine it with other conditions.

OperatorNameTrue whenExample with a = 5, b = 3
==equal toboth values are the samea == b is false
!=not equal tothe values differa != b is true
<less thanthe left value is smallera < b is false
>greater thanthe left value is largera > b is true
<=less than or equal tothe left value is smaller or the samea <= b is false
>=greater than or equal tothe left value is larger or the samea >= b is true

The six relational operators and what each one tests

java
Output
false
true
false
true
false
true
Notes on the code
  • Each println prints the boolean result of one comparison
  • Reading the output in order matches the rows of the table above

Comparing Numbers and Characters

Relational operators can compare values of any numeric type, so you can mix the same comparison pattern across int, long, double, and other numeric values. They can also compare char values. When characters are compared with < and >, Java uses each character's numeric Unicode value. This ordering is not the same as dictionary order. Every uppercase letter has a smaller Unicode value than every lowercase letter, so an uppercase letter is always less than a lowercase one, regardless of the letter itself.

java
Output
true
true
false
Notes on the code
  • 'Z' has a smaller Unicode value than 'a', so the first comparison is true
  • Any uppercase letter, including 'B', is less than any lowercase letter such as 'a'
  • The third line is false because 'a' is larger than 'B' in Unicode order

Comparing Boolean Values

The operators == and != can compare boolean values, including the results of other comparisons. This means a comparison such as a > b can itself be one side of another comparison. The result is still a boolean value. Comparing with == to true or false is valid Java, but it is usually unnecessary, because a boolean value can already be used directly as a condition.

java
Output
true
true
true
Notes on the code
  • done holds the result of the comparison a > b, which is true
  • Both done == true and done != false are true because done is true
  • The last line compares one comparison result with another

Testing for Double.NaN

Double.NaN is a special double value that represents a result which is not a number. Ordinary relational comparisons cannot be trusted to detect it. The expression x == Double.NaN is false for every value of x, including when x is itself NaN, so you cannot test for NaN by comparing to Double.NaN. The reliable test is the method call Double.isNaN(x), which returns true when x is NaN and false otherwise.

java
Output
false
true
false
Notes on the code
  • The division 0.0 / 0.0 produces NaN
  • The == comparison with Double.NaN is false even though x holds NaN
  • Double.isNaN(x) correctly reports that x is NaN

String Comparison and Object Storage

A String in Java is an object, and a variable of type String holds a reference to that object. The == operator checks where the objects are stored rather than comparing the text they contain. Two variables can hold different String objects that contain the same characters, and == will report them as unequal. To compare the contents of Strings, use equals() or compareTo() instead of a relational operator. equals() tells you whether two Strings contain the same text, and compareTo() tells you how two Strings are ordered.

s1variableString object Ahellos2variableString object Bhellorefers torefers to
Why can two Strings with identical text compare as unequal with ==? Each variable refers to its own String object, so == compares those two locations, not the characters inside them.
Code walkthrough
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
System.out.println(s1.compareTo(s2));
  1. 1
    Line 1 creates the first String object and stores its reference in s1
  2. 2
    Line 2 creates a second String object with the same text and stores its reference in s2
  3. 3
    Line 3 asks whether the two references point to the same object, which they do not, so the result is false
  4. 4
    Line 4 asks whether the text is the same, which it is, so the result is true
  5. 5
    Line 5 asks how the two Strings are ordered; equal Strings give 0
  • Two separate String objects are created, each holding the text hello
  • == returns false because the variables refer to different objects
  • equals() returns true because the contents match
  • compareTo() returns 0 because the two Strings are equal in ordering
Output
false
true
0
Best practice

When you want to know whether two Strings contain the same text, call equals(). When you need an ordering, call compareTo(). Reserve == for checking whether two references point to the same object.

Combining Conditions with && and ||

In English, complicated conditions use the words and, or, and not. Java provides boolean operators for the same purpose. The operator && means both conditions must be true, and || means at least one condition may be true. Read a compound expression from left to right. An && expression is true only when both operands are true. An || expression is true when at least one operand is true. Use && when every condition must hold, and use || when any one of several conditions is enough.

Pattern
A && B is true only when A is true and B is true; A || B is true when A is true or B is true or both are true
||whole condition&&groupage >= 18comparisonisStaffbooleanhasTicketbooleanleft operandright operandleft operandright operand
In a compound condition, which sub-expression decides the whole result? The expression (age >= 18 && hasTicket) || isStaff groups the && first, then combines that group with isStaff using ||.
Worked example

Deciding Whether a Condition Is True

Given age = 20, hasTicket = false, and isStaff = true, is the condition (age >= 18 && hasTicket) || isStaff true?

  1. 1
    Evaluate the first comparison

    age >= 18 is 20 >= 18, which is true.

  2. 2
    Evaluate the && group

    true && hasTicket becomes true && false, which is false, because both operands must be true.

  3. 3
    Evaluate the || with isStaff

    false || isStaff becomes false || true, which is true, because one true operand is enough.

  4. 4
    State the result

    The whole condition is true, and the decision came from isStaff.

Result

true

Short-Circuit Evaluation

The operators && and || use short-circuit evaluation. Java evaluates the left operand first. If that value already determines the result, the right operand is not evaluated at all. For && the result is already false when the left operand is false, so the right operand is skipped. For || the result is already true when the left operand is true, so the right operand is skipped. This matters in two ways: it saves work, and it prevents an invalid evaluation that would otherwise fail. Because the second operand may not run, it should not contain an action you depend on happening.

x != 0left operandy / x > 1right operandresult from righttrue or falseresult falseright operand skippedfalsetrueevaluated
When the left operand of && is false, which operands are evaluated and which are skipped? The right operand is skipped entirely, and the result is false.

The source describes the expression x != 0 && y / x > 1. Read it from left to right. The first operand asks whether x is not zero. The second asks whether y divided by x is greater than 1. Because the first operand guards the division, the division happens only when x is not zero.

Code walkthrough
int x = 0;
int y = 10;
if (x != 0 && y / x > 1) {
    System.out.println("big");
} else {
    System.out.println("skipped");
}
boolean ok = (x == 0) || (y / x > 1);
System.out.println(ok);
  1. 1
    Line 1 and 2 store the values 0 and 10
  2. 2
    The if condition evaluates x != 0 first, which is false
  3. 3
    Because the left operand of && is false, Java does not evaluate y / x > 1, so the else branch runs and skipped is printed
  4. 4
    Line 8 evaluates x == 0 first, which is true
  5. 5
    Because the left operand of || is true, Java skips y / x > 1 and ok becomes true
  • x is zero, so x != 0 is false
  • The && skips y / x entirely, so no division by zero occurs
  • x == 0 is true, so the || skips y / x and ok is true
Output
skipped
true

What do you think happens?

If the right operand of && divides by zero, will the program fail when the left operand is false?

  • Yes, the division always runs first

  • No, the right operand is skipped

Reveal answer
Answer:

No, the right operand is skipped

When the left operand of && is false, short-circuit evaluation skips the right operand, so the division never executes.

Reversing a Value with the ! Operator

Use ! to reverse a boolean value. Applying ! turns true into false and false into true. Unlike && and ||, the ! operator does not combine two boolean values. It changes one boolean value, so it takes a single operand. Because it can be applied to any boolean expression, parentheses matter. The expression !(a && b) reverses the whole result of the && test, while !a && b reverses only a before combining it with b.

Before
boolean test = (score > 50);
boolean result = test;

With score equal to 70, test is true, so result is true

After
boolean test = (score > 50);
boolean result = !test;

With the ! operator applied, result becomes false

java
Output
false
true
false
Notes on the code
  • !a reverses true to false
  • a && b is false, so !(a && b) is true
  • !a is false, so !a && b is false; the parentheses change the grouping

Mistakes Beginners Make with Boolean Operators

  • Common mistake

    Comparing String contents with ==

    What it looks like
    if (name == "Ada") used on a String read from input
    Why it fails

    == checks where the objects are stored, not the text they contain, so two Strings with identical text can compare as unequal.

    Do this instead
    Use name.equals("Ada") to compare contents.
  • Common mistake

    Testing for NaN with ==

    What it looks like
    if (x == Double.NaN)
    Why it fails

    The comparison with Double.NaN is false even when x holds NaN.

    Do this instead
    Use Double.isNaN(x).
  • Common mistake

    Assuming alphabetical order for mixed-case characters

    What it looks like
    'a' < 'B' expected to be true
    Why it fails

    char comparison uses Unicode values, and all uppercase letters come before all lowercase letters, so 'a' < 'B' is false.

    Do this instead

    Remember the Unicode ordering when you compare chars with < or >.

  • Common mistake

    Putting a risky action on the right of && or ||

    What it looks like
    x != 0 && y / x > 1 where x could be zero
    Why it fails

    Only the left operand is guaranteed to run; the right operand may be skipped and must not be needed for correctness of the guard.

    Do this instead

    Place the safety check on the left, as in x != 0 && y / x > 1.

  • Common mistake

    Forgetting that ! applies to the nearest operand unless parentheses change the grouping

EASY

Given int p = 4 and int q = 9, and given boolean flag = true, write the result of each expression before running it: p < q, p == q, !flag, flag || (p > q), and flag && (p > q). Then explain which operand of the last two expressions determined the result.

Hints
  • Compare each pair of numbers using the six relational operators
  • For || the result is true as soon as one operand is true
  • For && the result is false as soon as one operand is false

Locating the Cause of an Unexpected Result

When a compound condition gives an unexpected result, split it into its parts and evaluate each part separately, from left to right, using the grouping rules you have learned. Find the first sub-expression whose value you did not expect. Check whether a String was compared with == when equals() was needed, whether a NaN was tested with ==, whether a char comparison was assumed to be alphabetical, or whether a ! was applied to a larger expression than intended. Short-circuit evaluation also explains why a later part of an expression may never have run at all, so check whether the operand you expected to see was skipped.

MEDIUM

A condition reads !(age < 18) || hasPermission. Explain whether the expression is true for a 16-year-old without permission, and state which operand decides the result for a 30-year-old with permission.

Hints
  • Evaluate age < 18 first, then apply ! to that result
  • Short-circuit evaluation applies to the || operator

Key Takeaways

  • The six relational operators are ==, !=, <, >, <=, and >=, and each produces a boolean result that can be used as a condition.
  • Compare String contents with equals() or compareTo(), because == checks the object storage location rather than the text, and test for Double.NaN with Double.isNaN(x).
  • The && operator requires both operands to be true, || requires at least one, and ! reverses a single boolean value.
  • Short-circuit evaluation skips the right operand of && when the left is false and of || when the left is true, which can prevent an unnecessary or invalid evaluation.
  • To find the cause of an unexpected result, evaluate each sub-expression in grouping order and check the operand that was actually evaluated.