Skip to content
Study Hall
Lesson 1 of 3If Statements
Unit 3 · Lesson 1 of 3

Boolean Expressions and Comparison

Every decision a program makes reduces to one true-or-false value. Here is how those values are built, combined, and the two Java traps that quietly break them.

5 min read11 practice questionsAsk AI about this →

Key things to remember

  1. 1A boolean is only true or false; Java will not accept a number or a String where a condition is required.
  2. 2The six relational operators are ==, !=, <, >, <=, >=, and each produces a boolean.
  3. 3&& needs both sides true, || needs at least one, ! flips. Precedence runs !, then &&, then ||.
  4. 4Short-circuit: && skips its right side when the left is false, so a guard such as count != 0 && must come first.
  5. 5De Morgan: and .
  6. 6= assigns and == compares; for Strings use .equals(), because == compares references.

Before a program can choose between two paths, it has to ask a question that has exactly one of two answers. In Java that answer is a boolean — the value true or the value false, and nothing else. Unlike some languages, Java will not accept 0 or 1 or an empty String in place of a boolean, and that strictness is a gift: it means a condition that compiles is a condition that genuinely asks a yes-or-no question.

OperatorReads asExampleResult
==is equal to5 == 5true
!=is not equal to5 != 5false
<is less than3 < 7true
>is greater than3 > 7false
<=is less than or equal to7 <= 7true
>=is greater than or equal to6 >= 7false
The six relational operators. Each one produces a boolean, never a number.
Every condition in Java finally boils down to one of these three tables.a && ba || b!aabresulttruetruetruetruefalsefalsefalsetruefalsefalsefalsefalseabresulttruetruetruetruefalsetruefalsetruetruefalsefalsefalsearesulttruefalsefalsetrueNOT flips the answer.AND needs both true.OR needs only one.Short-circuit: && stops at the first false, || stops at the first true.if (n != 0 && 100 / n > 5) // the division never runs when n is 0That is why the safety check goes on the left of && — the order of the two sides matters.
Fig 1Truth tables for AND, OR and NOT, with the Java symbol for each.

Single comparisons are combined with the three logical operators. && is AND, and it is true only when both sides are true. || is OR, and it is true when at least one side is true — note that this is an inclusive or, so it is still true when both sides are true. ! is NOT, and it flips a boolean to its opposite. Their precedence runs ! first, then &&, then ||. Only && and || sit below the relational operators, which is why a < b && c > d needs no brackets at all. ! is different: it is a unary operator and binds tighter than the comparisons, so !age >= 13 does not mean what it looks like — Java reads it as (!age) >= 13, which will not even compile. Whenever you negate a comparison, bracket it: !(age >= 13).

int age = 16;
double mark = 83.5;

boolean teenager = age >= 13 && age <= 19;   // true
boolean weekend = false;
boolean canGo = teenager && weekend;          // false — both must hold
boolean interesting = mark >= 80 || weekend;  // true — one side is enough
boolean notYet = !teenager;                   // false

System.out.println(canGo + " " + interesting); // prints: false true
Comparisons produce booleans, and booleans can be stored in variables like any other value.

Short-circuit evaluation

Java evaluates && and || lazily, from left to right, and stops the instant the answer is certain. With &&, if the left side is false the whole thing must be false, so the right side is never evaluated at all. With ||, if the left side is true the right side is skipped. This is called short-circuit evaluation, and it is not merely an optimization — it is how you write a guard that protects the test that follows it.

int total = 0;
int count = 0;

// Safe: count != 0 is false, so the division is never attempted.
if (count != 0 && total / count > 5) {
    System.out.println("High average");
}

// Unsafe order: the division runs first and throws ArithmeticException.
// if (total / count > 5 && count != 0) { ... }
The guard must come first. Reversing the two sides turns a safe line into a crash.

De Morgan's laws

Sometimes the clearest way to express a condition is to negate a complicated one, and De Morgan's laws tell you how to push that negation inside. Negating an AND turns it into an OR of the negations, and negating an OR turns it into an AND of the negations. Both halves flip, and the connective flips too — forgetting the second half is the usual mistake.

De Morgan's laws, written with the logic symbols for AND, OR and NOT.
  • !(age >= 13 && age <= 19) is the same condition as age < 13 || age > 19.
  • !(isFull || isClosed) is the same condition as !isFull && !isClosed.
  • Notice that each comparison also flips: the opposite of >= is <, not <=.
  • Use whichever form reads more naturally out loud — they run identically.

The two traps that catch everyone

One equals sign stores. Two equals signs ask a question.=assignmentx = 5;puts 5 into x==comparisonx == 5true or false.equals()String contentss.equals("hi")letter by letterWhy == can lie about Stringsa"hi"at address 101b"hi"at address 205a == b → falseit compares 101 against 205a.equals(b) → trueit compares the letters h and iAlways use .equals() on Strings.Short identical literals often share one object, so == sometimes looks right — which makes the bug harder to catch.
Fig 2One equals sign stores a value; two equals signs ask a question.
int x = 5;
// if (x = 5) { }        // compile error: int cannot be converted to boolean

boolean done = false;
if (done = true) {       // COMPILES — and is a bug. It assigns, then tests true.
    System.out.println("This always runs, and done is now true.");
}

String a = "cat";
String b = "cat";
String c = new String("cat");
System.out.println(a == b);        // true  — both point at the same pooled literal
System.out.println(a == c);        // false — a different object in memory
System.out.println(a.equals(c));   // true  — same characters, which is what we meant
Two bugs that compile cleanly: assignment inside a condition, and == on Strings.
Always compare Strings with .equals
== on two Strings asks whether they are the same object in memory, not whether they hold the same characters. Java reuses identical literals from a pool, so == often appears to work during testing and then fails the moment the text comes from a Scanner or is built at run time. Use name.equals("yes") for an exact match, or name.equalsIgnoreCase("yes") when capitals should not matter.

Worked examples

Reveal one step at a time and try to beat it to the next line.

Example 1
A ride is open to people at least 12 years old AND at least 140 cm tall. Write the condition, then write the condition for being turned away.
Example 2
Evaluate !(x > 5) || (y % 2 == 0 && x != y) when x = 3 and y = 8.
Example 3
A menu reads a command with String cmd = sc.nextLine(); and then tests if (cmd == "quit"). It never matches, even when the user types quit. Explain and fix.

Where marks get lost

  • Comparing Strings with ==. It tests whether they are the same object, and it accidentally works on literals just often enough to hide the bug.
  • Writing if (done = true) on a boolean. It compiles, assigns true, and then always takes the branch.
  • Writing if (0 < mark < 50) as in mathematics. Java evaluates left to right, and the boolean from the first comparison cannot be compared with 50.
  • Negating only half of a condition: the opposite of a && b is !a || !b, not !a && !b.
  • Putting the guard second, as in total / count > 5 && count != 0. Short-circuit only helps when the protective test comes first.

Flashcards 10

What two values can a boolean hold?
List the six relational operators.
When is a && b true?
When is a || b true?
+ 6 more

Practice

1
Which line correctly tests whether the String answer holds the text yes?
2
What boolean value does (5 > 3) && (2 > 4) produce?
3
Which condition is equivalent to !(score >= 50 && attempts < 3)?
4
Why does if (count != 0 && total / count > 5) never crash when count is 0?
5
How many rows does a complete truth table for three boolean variables have?
6
A program contains boolean ready = false; followed by if (ready = true) { ... }. What happens?
7
Rewrite !(raining || cold) without the outer NOT.
8
Order these operators by the sequence Java applies them in a single expression, first to last.
  1. 1Relational comparisons such as < and >=
  2. 2|| (OR)
  3. 3&& (AND)
  4. 4! (NOT)
9
Given String a = "cat"; and String c = new String("cat");, what does a == c produce?
10
Match each Java operator to what it asks or does.
==
=
!=
!
11
Which expression correctly tests that mark is between 50 and 79 inclusive?

Spot a mistake on this page? Let us know