Lesson 2.5: Compound Boolean Expressions
Lesson 2.5: Compound Boolean Expressions
Key Vocabulary
| Term | Definition |
|---|---|
| compound boolean expression | A boolean expression formed by combining two or more boolean sub-expressions using the logical operators !, &&, or ||. (EK 2.5.A.1) |
| ! (NOT) | Logical negation. !a is true when a is false, and false when a is true. Highest logical precedence. |
| && (AND) | Logical conjunction. a && b is true only when both a and b are true. If a is false, b is not evaluated (short-circuit). |
| || (OR) | Logical disjunction. a || b is true when at least one of a or b is true. If a is true, b is not evaluated (short-circuit). |
| short-circuit evaluation | Stopping evaluation of a compound expression as soon as the result is determined. Java guarantees this behavior for && and ||. (EK 2.5.A.2) |
| logical precedence | The order Java evaluates logical operators: ! first, then &&, then ||. Arithmetic and relational operators all evaluate before any logical operator. |
The Three Logical Operators (EK 2.5.A.1)
Topic 2.5 introduces the logical operators that combine boolean expressions into compound conditions. These are essential for writing realistic conditions: real programs rarely check just one thing at a time. A login system checks username AND password. A discount applies when age is under 13 OR over 65. A validation rejects input when it is NOT in the valid range.
CED Connection (EK 2.5.A.1)
"Logical operators ! (not), && (and), and || (or) are used with Boolean expressions... An expression involving logical operators evaluates to a Boolean value." The precedence order is also mandated: ! first, && second, || last.
Truth tables for all three operators
| a | b | !a | a && b | a || b |
|---|---|---|---|---|
| true | true | false | true | true |
| true | false | false | false | true |
| false | true | true | false | true |
| false | false | true | false | false |
Worked Example — All Three Operators
int age = 25; boolean hasTicket = true; boolean isMember = false; // AND: both must be true System.out.println(age >= 18 && hasTicket); // true && true = true System.out.println(age >= 18 && isMember); // true && false = false // OR: at least one must be true System.out.println(hasTicket || isMember); // true || false = true System.out.println(age < 13 || age >= 65); // false || false = false // NOT: flip the boolean System.out.println(!hasTicket); // !true = false System.out.println(!isMember); // !false = true
Operator Precedence (EK 2.5.A.1)
The CED specifies the evaluation order: ! binds tightest (like unary minus), then &&, then ||. All arithmetic and relational operators evaluate before any logical operator. The full chain from highest to lowest: arithmetic → relational → ! → && → ||.
Worked Example — Precedence Step by Step
// Expression: !a || b && c where a=false, b=true, c=false // Step 1: evaluate ! first // !false = true // Step 2: evaluate && before || // b && c = true && false = false // Step 3: evaluate || // true || false = true // With parentheses making it explicit: (!a) || (b && c) = true || false = true // Common mistake: treating || and && as same precedence // WRONG reading: (!a || b) && c = (true || true) && false = true && false = false
When in doubt, add parentheses to make your intent explicit. This is especially important in AP FRQ solutions where clarity is graded.
Short-Circuit Evaluation (EK 2.5.A.2)
Java uses short-circuit evaluation for && and ||: if the result of the compound expression can be determined from the first operand alone, the second operand is never evaluated. This is a performance optimization that also has practical consequences when the second operand has side effects.
| Operator & first operand | Short-circuit behavior |
|---|---|
| && when first is false | Result must be false regardless of second. Second is NOT evaluated. |
| && when first is true | Result depends on second. Second IS evaluated. |
| || when first is true | Result must be true regardless of second. Second is NOT evaluated. |
| || when first is false | Result depends on second. Second IS evaluated. |
Worked Example — Short-Circuit Prevents NullPointerException
String name = null;
// SAFE: && short-circuits when name == null is true
// The second operand (name.length() > 0) is never reached
if (name != null && name.length() > 0) {
System.out.println("Valid name");
}
// UNSAFE: checking length before null check
if (name.length() > 0 && name != null) { // NullPointerException!
System.out.println("Valid name");
}
Short-circuit evaluation makes the order of operands in a compound expression meaningful. The null check must come first because the second operand is only safe to evaluate when the first confirms the object is not null.
AP Trap: !a on a Non-Boolean
! only works on boolean values. !x where x is an int is a compile error. A common mistake is writing !score when the intent is score == 0 or !(score > 0). Similarly, !x == 0 tries to negate x first, not the comparison. Write !(x == 0) or x != 0 instead.
AP Trap: Confusing && and || Logic
"A number is between 1 and 10" requires n >= 1 && n <= 10 (AND — both must be true simultaneously). Students often write n >= 1 || n <= 10 (OR), which is true for almost every integer. Remember: AND narrows the result; OR widens it.
AP Trap: Short-Circuit Order Matters
If the second operand of && or || has a side effect (method call, increment), and short-circuit prevents its evaluation, that side effect does not happen. AP exam questions test this: "how many times is method X called in this expression?" The answer depends on short-circuiting.
Real-World Connection
Compound boolean expressions power virtually every real software decision. A flight booking system checks seatsAvailable > 0 && paymentValid && !flightCancelled before confirming a reservation. A video game grants a bonus when levelComplete || timeBonus > 0. A form validator rejects a password when password.length() < 8 || !containsUpperCase || !containsDigit. Short-circuit evaluation is critical for null-safety patterns that appear in virtually every production Java codebase.
Summary
-
Three logical operators:
!(NOT),&&(AND),||(OR). All produce boolean values. (EK 2.5.A.1) - ! inverts a boolean. Only works on boolean operands.
- && is true only when BOTH operands are true.
- || is true when AT LEAST ONE operand is true.
-
Precedence:
!first, then&&, then||. Arithmetic and relational operators evaluate before any logical operator. -
Short-circuit (EK 2.5.A.2):
&&skips right side when left isfalse;||skips right side when left istrue. -
AND narrows; OR widens. "Between 1 and 10" uses
&&, not||.
Logical Operators
Logical operators combine or modify boolean values to build compound boolean expressions.
The Three Logical Operators
!a // NOT: true if a is false a && b // AND: true only if BOTH a and b are true a || b // OR: true if a is true, b is true, or both
Practical Examples
int age = 25;
boolean hasTicket = true;
// Both conditions must be true
if (age >= 18 && hasTicket) {
System.out.println("Enter");
}
// Either condition suffices
if (age < 13 || age >= 65) {
System.out.println("Discount");
}
Operator Precedence
Logical operators have a defined precedence: ! is evaluated first, then &&, then ||. Use parentheses to override precedence or improve readability.
Precedence Example
// Without parens: && binds tighter than || x > 1 || x > 3 && x < 10 // Evaluated as: x > 1 || (x > 3 && x < 10)
AP Trap: ! Precedence
! applies to the immediately following operand. !x == 0 means (!x) == 0, not !(x == 0). Since x is an int, !x is a compile error. Always write !(expression) or use != instead.
Short-Circuit Evaluation
Java stops evaluating a compound expression as soon as the result is determined:
Short-Circuit Rules
// && short-circuits if first operand is false false && anything // second operand never evaluated // || short-circuits if first operand is true true || anything // second operand never evaluated
This prevents errors like division by zero: x != 0 && y / x > 2 is safe because if x == 0, the division is never reached.
Practice Questions
x > 3 && x < 10 when x = 5?true
false
5
x < 3 || x > 10 when x = 5?true
false
5
int n = 7; System.out.println(!(n > 5));
7
true
0
false
1 <= n <= 100
n >= 1 || n <= 100
n >= 1 && n <= 100
!(n < 1) || !(n > 100)
int a = 0; System.out.println(a != 0 && 10 / a > 2);
true
false
a || b && c evaluate to when a=false, b=true, c=false?false
true
false && expr evaluates to false without evaluating expr
true || expr evaluates to true without evaluating expr
int x = 5; boolean r = x > 2 && x < 6 || x == 10; System.out.println(r);
false
true
5
Mastery: Compound Expressions
x = 3 and y = 8?if (x > 0 && y > 5) {
System.out.println("Both");
} else if (x > 0 || y > 5) {
System.out.println("One");
} else {
System.out.println("Neither");
}
count > 0 && total / count > 10. Why is the order of operands important here?!(x > 5 && y < 3)?!(x > 5) && !(y < 3)
x <= 5 && y >= 3
x <= 5 || y >= 3
x > 5 || y < 3
p = true and q = false?boolean r = !p || q && !q; System.out.println(r);
true
false
true then false
Short-Circuit Safety Pattern
Short-circuit evaluation is commonly used as a safety guard. The pattern obj != null && obj.method() is safe because if obj is null, the method call never happens. If the order were reversed, a NullPointerException would be thrown. Can you think of other situations where the order of operands in a compound expression matters beyond just performance?
Get in Touch
Whether you're a student, parent, or teacher — I'd love to hear from you.
Just want free AP CS resources?
Enter your email below and check the subscribe box — no message needed. Students get daily practice questions and study tips. Teachers get curriculum resources and teaching strategies.
Message Sent!
Thanks for reaching out. I'll get back to you within 24 hours.
Prefer email? Reach me directly at [email protected]