3.3 Decision Making: if, if-else, and the Ternary Operator
Key Takeaways
- Conditions in Java if statements must evaluate strictly to a primitive boolean or Boolean wrapper; numeric values such as 0 or 1 do not convert to boolean and cause compile-time errors.
- Without enclosing curly braces {}, an if or else block governs only the single statement immediately following it, causing misleading indentation to introduce severe logical bugs.
- The dangling else ambiguity is resolved by Java's formal grammar rule: an else binds to the closest preceding unmatched if within the same enclosing block scope.
- The ternary operator (condition ? expr1 : expr2) is an expression that yields a value and conditionally short-circuits, evaluating only the branch selected by the condition.
- Both branches of a ternary expression must evaluate to types compatible with the receiving variable, and mixed numeric types undergo binary numeric promotion (e.g., int and double branches promote the integer to double).
3.3 Decision Making: if, if-else, and the Ternary Operator
[!NOTE] Exam Focus: Oracle's "Using Decision Statements" topic area tests candidate precision on Java decision statements. Key examination traps include accidental assignment inside
ifconditions (if (b = true)vsif (x = 5)), unbraced single-statement execution with deceptive indentation, the dangling else scoping rule, and ternary operator branch evaluation rules and type compatibility.
In standard program execution, instructions execute sequentially from top to bottom. Decision-making statements introduce conditional branching, allowing the Java Virtual Machine to selectively execute different blocks of code based on dynamic runtime criteria.
1. Strict Boolean Condition Requirements & Common Traps
Unlike languages such as C, C++, or Python where numbers can serve as boolean conditions (e.g., 0 is falsy and non-zero is truthy), Java is strictly typed: the conditional expression governing an if statement must evaluate strictly to a primitive boolean or a Boolean wrapper object.
int count = 5;
// COMPILE ERROR: incompatible types: int cannot be converted to boolean
// if (count) {
// System.out.println("Count is positive");
// }
// Valid Java syntax:
if (count > 0) {
System.out.println("Count is positive");
}
The Assignment vs. Equality Trap
A classic 1Z0-811 exam question tests accidental assignment (=) instead of relational equality (==) inside an if header:
int score = 90;
// if (score = 100) { } // COMPILE ERROR: int cannot be converted to boolean
However, if the variable being tested is of type boolean, assigning a value inside the condition compiles cleanly and creates a deceptive trap:
boolean isEligible = false;
// TRAP: This is ASSIGNMENT (=), not equality (==)!
if (isEligible = true) {
System.out.println("Granted access"); // ALWAYS EXECUTES!
}
System.out.println("isEligible is now: " + isEligible); // Prints: true
[!WARNING] Exam Watch: When inspecting
if (var = value)on the exam:
- If
varis numeric or an object reference, compilation fails (incompatible types).- If
varisboolean, the code compiles, mutates the variable with the assigned value, and branches based on that new boolean value!
2. The if, if-else, and if-else-if Statements
The Single if Statement
Executes its controlled statement or block if and only if the boolean condition evaluates to true:
if (temperature > 100) {
System.out.println("High temperature alert");
}
The if-else Statement
Provides two mutually exclusive branches. Exactly one branch executes:
if (balance >= price) {
balance -= price;
System.out.println("Purchase successful");
} else {
System.out.println("Insufficient funds");
}
The if-else-if Ladder
When multiple non-overlapping conditions must be tested sequentially, the if-else-if ladder evaluates conditions from top to bottom. The first condition that evaluates to true triggers its block, and all remaining branches are skipped:
int marks = 85;
char grade;
if (marks >= 90) {
grade = 'A';
} else if (marks >= 80) {
grade = 'B'; // Matches: assigns 'B' and skips subsequent branches
} else if (marks >= 70) {
grade = 'C';
} else {
grade = 'F';
}
[!TIP] Order Matters: In an
if-else-ifladder, placing a broad condition before a specific condition causes the specific block to become unreachable dead code. For example, testingmarks >= 60beforemarks >= 90prevents'A'from ever being awarded.
3. Block Scoping, Indentation Traps, and the Empty Statement
In Java, curly braces {} group multiple statements into a single compound block. If curly braces are omitted, an if or else clause controls only the single statement immediately following it.
The Indentation Trap
Java compilers ignore whitespace and indentation. Indentation does not define block scope:
int score = 50;
if (score >= 60)
System.out.println("Passed");
System.out.println("Keep up the good work!"); // UNCONDITIONAL: Always executes!
Because braces are absent, only System.out.println("Passed"); belongs to the if. The second print statement executes unconditionally regardless of score, printing Keep up the good work!. Always use curly braces {} in production code to avoid this trap.
The Semicolon Trap (Empty Statement)
A misplaced semicolon ; immediately following an if condition creates an empty statement, rendering the condition useless:
int x = 5;
if (x > 10); // TRAP: The semicolon terminates the if statement here!
{
System.out.println("x is greater than 10"); // ALWAYS EXECUTES!
}
4. The Dangling Else Ambiguity & JLS Resolution Rule
When if statements are nested without curly braces, an ambiguous syntactic situation known as the dangling else occurs:
int a = 5;
int b = 15;
if (a > 10)
if (b > 10)
System.out.println("Both are greater than 10");
else
System.out.println("a is 10 or less"); // Which if does this else belong to?
Does the else belong to the outer if (a > 10) or the inner if (b > 10)?
Java's Formal Resolution Rule (JLS §14.5)
In Java, an unbraced
elsealways binds to the closest preceding unmatchedifstatement within the same block scope.
In the code above:
- The
elsebelongs to the innerif (b > 10). - When
a > 10is tested,5 > 10evaluates tofalse. - Because the entire inner
if-elseconstruct is contained inside the outerifstatement, the inner construct is completely bypassed. - Nothing is printed at all!
// What the compiler actually constructs:
if (a > 10) {
if (b > 10) {
System.out.println("Both are greater than 10");
} else {
System.out.println("a is 10 or less"); // Bound to inner if!
}
}
To bind the else to the outer if, curly braces must explicitly enclose the inner if:
if (a > 10) {
if (b > 10) {
System.out.println("Both are greater than 10");
}
} else {
System.out.println("a is 10 or less"); // Bound to outer if
}
5. The Ternary Conditional Operator (? :)
The ternary operator is Java's only operator that takes three operands. It acts as an inline, expression-level alternative to a standard if-else block.
Syntax
booleanCondition ? expressionIfTrue : expressionIfFalse
int age = 20;
String status = (age >= 18) ? "Adult" : "Minor"; // Evaluates to "Adult"
Expression vs. Statement Distinction
The ternary construct is an expression, meaning it evaluates to a concrete value. It cannot be used as a standalone statement:
int x = 10, y = 20;
// COMPILE ERROR: not a statement
// (x > y) ? System.out.println(x) : System.out.println(y);
// CORRECT: Pass the ternary expression result as an argument
System.out.println((x > y) ? x : y);
Short-Circuit Evaluation in Ternary Operators
Just like the short-circuit logical operators (&&, ||), the ternary operator evaluates only one branch expression at runtime. If booleanCondition is true, expressionIfTrue is evaluated and expressionIfFalse is skipped; if false, only expressionIfFalse is evaluated:
int count = 5;
int result = (count > 0) ? ++count : --count;
System.out.println("count=" + count + ", result=" + result);
// Prints: count=6, result=6 (--count is NEVER evaluated!)
6. Type Compatibility & Numeric Promotion in Ternary Branches
On Exam 1Z0-811, you must verify that both ternary branch expressions are compatible with the target receiving variable.
Branch Type Rules
- Both branch expressions must yield types that can be converted or assigned to the target variable.
- When one branch is an integer and the other is a floating-point number, binary numeric promotion widens the integer branch to match the floating-point branch:
int n = 10;
double val = true ? n : 2.5;
System.out.println(val); // Prints: 10.0 (n is widened to double 10.0!)
- Incompatible branch types trigger a compile-time error:
// COMPILE ERROR: incompatible types: String cannot be converted to int
// int num = (5 > 2) ? 10 : "Error";
7. Nested Ternary Expressions
Ternary expressions can be chained or nested to evaluate multiple conditions. Because the ternary operator is right-associative, chained operators group from right to left:
int score = 78;
String grade = (score >= 90) ? "A"
: (score >= 80) ? "B"
: (score >= 70) ? "C"
: "F";
System.out.println(grade); // Prints: C
What is the console output of the following Java program?
int x = 6;
int y = 14;
if (x > 10)
if (y > 10)
System.out.print("Alpha");
else
System.out.print("Beta");
System.out.print("Gamma");
What is printed after executing the following Java code snippet?
boolean enabled = false;
int counter = 100;
if (enabled = true) {
counter += 50;
} else {
counter -= 50;
}
System.out.println("enabled=" + enabled + ", counter=" + counter);
What is the evaluated output of the following code involving a ternary expression with side effects?
int score = 75;
int bonus = 10;
double total = (score >= 80) ? ++bonus + score : bonus++ + (double)score / 2;
System.out.println("bonus=" + bonus + ", total=" + total);