Control flow questions test whether you can predict exactly which statement executes next.
Think in this order:
- Condition evaluation
- Branch/loop selection
- Jump statements (break, continue, return, throw)
- finally execution guarantees
Short-circuit operators:
- && : if left is false, right is not evaluated.
- || : if left is true, right is not evaluated.
Non-short-circuit operators:
- & and | with booleans evaluate both sides.
This matters for division-by-zero and side effects inside conditions.
In Java, if condition must be boolean.
- if (a = 10) does not compile because assignment expression is int, not boolean.
Classic switch behavior:
- Matching case starts execution.
- Without break, fall-through continues into next cases.
- default runs when no case matches (or after fall-through if reached).
String switch notes:
- Compiler typically uses hash-based dispatch plus equals check.
- Hash collision does not break correctness because equals is still checked.
Modern switch supports:
- Arrow labels: case X -> ...
- Expression form that returns a value.
Rules:
- No fall-through with arrow syntax.
- Switch expressions must be exhaustive.
- Use yield in block cases when returning a value from switch expression.
for/while/do-while fundamentals:
- for init variable scope is limited to loop block.
- do-while body executes at least once.
- Infinite loops occur when condition never becomes false.
Evaluation order in for loop:
- init -> condition -> body -> update -> condition -> ...
break:
- Exits nearest loop/switch by default.
- Labelled break exits the named outer loop.
continue:
- Skips remaining body and goes to next iteration.
- Labelled continue jumps to next iteration of named outer loop.
Ternary is right-associative:
- a ? b : c ? d : e means a ? b : (c ? d : e)
Type selection rules can promote operands to common type. In mixed numeric wrappers, result may be a promoted numeric type rather than one operand's exact wrapper.
Compile-time unreachable examples:
- while(false) { ... } is a compile-time error.
Reason:
- Compiler detects definitely unreachable statements for constant-false loops.
finally executes even when:
- return runs in try/catch
- break/continue occurs
- exception is thrown
If finally returns, it overrides earlier return values and can suppress exceptions.
for-each loop variable is a copy of each element reference/value for that iteration.
- Reassigning loop variable does not modify collection contents.
- To modify mutable element state, mutate the object itself.
- To replace elements, use index-based update or list iterator (if mutable collection).
Pattern switch supports:
- Type patterns (case Integer i -> ...)
- Guarded patterns (case Integer i when i > 0 -> ...)
- case null handling
- Record patterns
Important rules:
- Order matters; broader patterns can dominate narrower ones.
- Dominated case labels cause compile-time error.
- Exhaustiveness is required for switch expressions, especially with sealed hierarchies.
- Pattern variables exist only in their matching case scope.
Good style:
- Prefer guard clauses over deep nesting.
- Replace magic numbers with enums/constants.
- Use multiple early returns when clarity improves.
- Do not use exceptions for normal control flow in hot paths.
- Choose loop vs stream based on readability and performance context.
For any control-flow snippet:
- Mark entry point and initial variable values.
- Evaluate conditions in exact order.
- Track loop iteration boundaries.
- Apply break/continue/return labels precisely.
- Apply finally execution before method exit.
- For switch, verify matching, fall-through (if classic), and exhaustiveness (if expression).
- For pattern switch, check dominance, guards, and null handling.
- && vs & and side effects
- Assignment-in-condition compile errors
- Classic switch fall-through
- String switch collision understanding
- Loop termination and scope
- Labelled break and continue
- do-while execution guarantee
- Ternary associativity and type selection
- Dead code detection
- try/finally return override
- for-each modification behavior
- Enhanced switch and yield
- Java 21 pattern matching: guards, dominance, exhaustiveness, sealed types, record patterns, null