Java Boolean Logic and Selection

Build a clear understanding of Java Boolean expressions, logical operators, selection statements, nested branching, equivalent logic, and systematic code tracing for AP Computer Science A.

Boolean Values and Comparisons

Java uses the primitive type boolean to store one of two values: true or false. A produces one of those two values and can be assigned to a variable or used directly as the condition of an if statement.

For example, int temperature = 72; followed by boolean isWarm = temperature >= 70; makes isWarm equal to true, because the comparison is true. The comparison can also be used directly in if (temperature >= 70) { ... }.

Java requires an if condition to have type boolean or Boolean; it does not automatically treat an integer such as 1 or 0 as a Boolean value.

Comparing values

Relational and equality operators produce Boolean results:

  • == means equal to.

  • != means not equal to.

  • < means less than.

  • > means greater than.

  • <= means less than or equal to.

  • >= means greater than or equal to.

Do not confuse assignment with comparison. score = 90 stores a value, whereas score == 90 tests whether the value is equal to 90.

For primitive values such as int, == compares the actual values. For objects such as String, == compares references rather than character contents. Use equals for content comparison, as in first.equals(second).

Takeaway: A always evaluates to true or false. Distinguish the assignment operator = from the ==, and use equals for the contents of String objects.

Logical Operators and Compound Conditions

Logical operators allow a program to combine or reverse Boolean expressions. The three basic operators are NOT !, AND &&, and OR ||.

  • !condition is true when condition is false.

  • a && b is true only when both a and b are true.

  • a || b is true when at least one of a and b is true.

Use AND when every requirement must be satisfied. For example, if (age >= 18 && hasIdentification) { ... } requires both the age comparison and hasIdentification to be true. Use OR when any one of several alternatives is sufficient, as in if (isWeekend || isHoliday) { ... }.

Precedence and parentheses

Without parentheses, Java evaluates logical operators in this order:

  1. !

  2. &&

  3. ||

Therefore, a || b && c is grouped as a || (b && c). Parentheses make the intended grouping easier to read, as in if ((temperature > 80) && (isHumid || isSunny)) { ... }.

Short-circuiting

Java uses for && and ||:

  • With &&, a false first operand makes the complete condition false, so Java skips the second operand.

  • With ||, a true first operand makes the complete condition true, so Java skips the second operand.

For example, if (divisor != 0 && 100 / divisor > 2) { ... } is safe when divisor is zero. The first condition is false, so Java does not evaluate the division and avoids division by zero.

Takeaway: Use && for requirements that must all be true, || for alternatives, and parentheses whenever they improve clarity. Remember that can prevent later operands from running.

Selection Statements

Selection changes the normal sequential flow of a program by choosing which statements execute.

One-way selection

An if statement executes its body only when its condition is true. For example, if (score >= 60) { System.out.println("Passing grade"); } prints a message only when the comparison succeeds.

Braces are strongly recommended because they clearly show which statements belong to the condition. Without braces, only the next statement belongs to the if, regardless of indentation. Thus, in if (score >= 60) System.out.println("Passing grade"); System.out.println("This always executes");, the second output statement is not controlled by the if.

Two-way selection

An if-else statement chooses exactly one of two alternatives. In if (number % 2 == 0) { ... } else { ... }, the first body runs for an even number and the second body runs for an odd number. Use this structure when the true and false cases require different actions.

Multiway selection

An checks conditions from top to bottom and executes the body of the first true condition. For example, a grading chain can test score >= 90, then score >= 80, then score >= 70, followed by an else case.

Order matters. A broad test such as score >= 70 placed before score >= 90 would capture a score of 95 before the more specific test could run. More specific or restrictive conditions generally belong before broader conditions.

Takeaway: Use if for one optional action, if-else for two alternatives, and an for ordered multiple alternatives. Use braces to make the structure unambiguous.

Nested Conditionals and Branch Structure

A places one conditional statement inside another. The inner condition is reached only when execution enters the outer body.

For example, an outer test can check age >= 18. If that test succeeds, an inner test can check hasPermission; otherwise, the program can report that the age requirement was not met. This lets the program provide different responses for different failure cases.

The successful case can sometimes be written more compactly as if (age >= 18 && hasPermission) { ... }. Use a compound condition when the requirements lead to the same action. Use nesting when separate outcomes or messages are important.

Matching else with if

The dangling else rule states that an else matches the nearest unmatched if at the same structural level. In if (a) { if (b) { ... } else { ... } }, the else belongs to the inner if (b), not the outer if (a). Braces make this relationship explicit and prevent ambiguity.

Takeaway: Trace outer conditions before inner ones. Use braces whenever nested conditionals could make the matching else unclear.

Equivalent Boolean Logic

Two Boolean expressions are logically equivalent when they produce the same result for every possible combination of input values. Equivalent expressions can help simplify code, verify a rewrite, or convert between nested and compound conditionals.

Negation rules

Double negation cancels itself: !!a has the same result as a. Negating a comparison reverses its relationship:

  • !(x == y) is equivalent to x != y.

  • !(x != y) is equivalent to x == y.

  • !(x < y) is equivalent to x >= y.

  • !(x > y) is equivalent to x <= y.

  • !(x <= y) is equivalent to x > y.

  • !(x >= y) is equivalent to x < y.

rewrite a negated compound condition by negating each part and switching AND with OR:

  • !(a && b) is equivalent to !a || !b.

  • !(a || b) is equivalent to !a && !b.

For example, !(age >= 13 && age <= 19) and age < 13 || age > 19 describe the same ages outside the teenage range.

Rewriting nested logic

A nested structure such as if (a) { if (b) { action(); } } is equivalent to if (a && b) { action(); } when the only desired action is action(). The nested version may still be clearer when different failed requirements need different messages.

Equivalent code is not always equally readable. Prefer the form that most directly communicates the intended rule.

Takeaway: When negating a compound condition, negate each component and switch AND with OR. Then test representative cases to confirm that the rewrite preserves behavior.

Tracing and Common Errors

Tracing conditional code means following values, precedence, braces, and evaluation order rather than relying on indentation or intuition.

Use this sequence:

  1. Record the current value of every variable.

  2. Evaluate arithmetic inside comparisons.

  3. Evaluate relational and equality operators.

  4. Apply !, then &&, then ||, unless parentheses change the order.

  5. Follow the selected branch.

  6. Continue with the statements after the conditional.

Consider int x = 8; int y = 3; followed by if (x > 5 && y < 2 || x == 8) { ... } else { ... }. Apply precedence first: (x > 5 && y < 2) || (x == 8). Substitute the values: (true && false) || true. Simplify to false || true, which is true, so the first branch executes.

Frequent mistakes

  • Do not use = when a comparison with == is intended.

  • Do not confuse &&, which requires both conditions, with ||, which requires at least one.

  • Do not assume indentation changes the statements controlled by an if; braces determine the structure.

  • Do not use separate if statements when only one mutually exclusive result should print. A score of 95 would satisfy both score >= 90 and score >= 80 if those tests were separate.

  • Do not assume every operand of a compound condition executes; may skip an operand.

Final takeaway: Reduce a condition one step at a time, respect parentheses and operator precedence, and trace only the branch that Java actually selects.