Switch Expressions & Statements practice questions

From OCP Java SE 25 (1Z0-831) · 16 questions on this topic

Switch Expressions & Statements practice questions from OCP Java SE 25 (1Z0-831). This pack has 16 questions tagged Switch Expressions & Statements, drawn from its timed mock exams. 8 of them are worked through in full below — the question, every option, why each is right or wrong, and the explanation.

Worked examples for Switch Expressions & Statements

  1. Question 1

    Which two statements about switch in Java are correct? (Choose two.)

    1. A. In a switch statement with colon labels, control falls through to the next label unless a break (or other jump) intervenesCorrect answer

      Correct: colon labels in a switch statement fall through, so after a matching label runs execution continues into subsequent labels until a `break` (or another jump such as `return`) intervenes.

    2. B. A switch statement over an enum must cover every enum constant or provide a default, otherwise it does not compile

      Only a switch expression must be exhaustive; a switch statement over an enum may omit constants and simply do nothing for unlisted values, so it still compiles and runs.

    3. C. The default label may be written before the case labels in a switch blockCorrect answer

      Correct: the `default` label is not required to be last; it may be placed before, between, or after the `case` labels, and its position does not change which label the selector matches.

    4. D. return may be used inside an arm of a switch expression to make that value the result of the switch

      A switch expression produces its value only via `yield` (or an arrow expression); a `return` that leaves the switch expression is a compile error.

    Explanation

    Fall-through and tolerance of uncovered values are properties of the colon statement form, while exhaustiveness and no-fall-through belong to the expression and arrow forms. The `default` label may appear anywhere in the block, not only last, without changing which label the selector matches. A switch expression yields its value rather than returning it, so any `return` leaving the expression is a compile error.

  2. Question 2

    The loop condition below is already false before the loop is reached. What is printed? ```java public class Main { public static void main(String[] args) { int i = 5; int count = 0; do { count++; i++; } while (i < 5); System.out.println(count + " " + i); } } ```

    1. A. 1 6Correct answer

      A do-while executes its body once before testing, so the counter becomes 1 and the index becomes 6, then the false condition ends the loop.

    2. B. 0 5

      This is the result of a while loop, which tests before the first iteration; a do-while always runs its body at least once.

    3. C. 1 5

      Runs the body once but assumes the index is not incremented; the body increments it before the false test.

    4. D. 0 6

      Assumes the counter increment is skipped; the body runs once in full before the condition is checked.

    Explanation

    A do-while statement runs its body first and evaluates the condition afterward, so the body always executes at least once even when the condition is initially false. A while loop tests before the first iteration, which is the whole behavioural difference between the two forms.

  3. Question 3

    What does this print? ```java public class Main { public static void main(String[] args) { int count = 0; search: for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { count++; if (i + j == 2) { break search; } } } System.out.println(count); } } ```

    1. A. 1

      1 assumes the break fires on the first iteration, but 0+0 is not 2, so the loops keep running.

    2. B. 3Correct answer

      `count` increments on each inner iteration until `i + j == 2` triggers `break search`, which exits both loops; that first happens at i=0,j=2 after three increments.

    3. C. 5

      5 is what a plain unlabeled `break` would give: it would exit only the inner loop, and the outer loop would keep running.

    4. D. 9

      9 ignores the labeled break entirely and counts all 3x3 iterations.

    Explanation

    A labeled `break` abandons the entire loop named by the label, not just the innermost loop, so it exits both nested loops at once. Counting the increments up to the iteration where the break condition first holds gives the result. An unlabeled break would instead leave only the inner loop while the outer loop continued.

  4. Question 4

    This switch expression covers every constant of the enum and has no default branch. What is printed? ```java public class Main { enum Level { LOW, MID, HIGH } static int cost(Level l, int units) { return switch (l) { case LOW -> units; case MID -> { int c = units * 2; if (units > 3) { c -= 1; } yield c; } case HIGH -> units * 3; }; } public static void main(String[] args) { System.out.println(cost(Level.MID, 5) + " " + cost(Level.HIGH, 2) + " " + cost(Level.LOW, 4)); } } ```

    1. A. 9 6 4Correct answer

      Correct: no default is needed because every enum constant has a case, so it is exhaustive; MID sets c=10 then subtracts 1 to 9, HIGH is 2*3=6, and LOW is 4, giving 9 6 4.

    2. B. 10 6 4

      Skips the if inside the block arm, as if yield were bound to c at its declaration; yield returns the value of c at the moment it executes, after the if has run, so MID yields 9 not 10.

    3. C. Compilation fails: a switch expression must have a default branch

      Assumes default is always mandatory in a switch expression; it is required only when the case labels do not already cover every value of the selector, and here all three enum constants are covered.

    4. D. 9 5 4

      Applies the block arm's -1 adjustment to the HIGH arm as well; each arrow arm is independent, so a block arm's locals and side effects never leak into a sibling arm.

    Explanation

    Trace: it compiles, because a switch expression only needs to be *exhaustive*, and an enum selector whose every constant has a case label already is — LOW, MID and HIGH are all covered, so no `default` is required. Then: `cost(MID, 5)` enters the block arm, sets `c = 10`, and since 5 > 3 the `if` fires and drops it to 9, which `yield` hands back as the arm's value; `cost(HIGH, 2)` is 2 * 3 = 6; `cost(LOW, 4)` is 4. Output is `9 6 4`. Why the others are wrong: `10 6 4` skips the `if` inside the block arm, as if `yield` were bound to `c` at its declaration. `yield` returns the value of `c` at the moment it executes, after every statement above it has run. `9 5 4` applies the block arm's `-1` adjustment to the HIGH arm as well (2 * 3 - 1 = 5). Each arrow arm is independent; a block arm's locals and side effects never leak into a sibling arm. `Compilation fails: a switch expression must have a default branch` encodes the common belief that `default` is mandatory in a switch expression. It is only mandatory when the case labels do not already cover every possible value of the selector — which they do here. Exam tip: a switch expression must be exhaustive; a switch *statement* need not be. Exhaustiveness over an enum can be reached without `default`, and doing so is deliberately better style: add a fourth constant to the enum later and this switch stops compiling, which is the warning you want. Bolt a `default` on and the same change compiles silently and mis-prices the new level. Also note the mixed shapes here — an arrow arm may be a single expression *or* a block that ends in `yield`, and the two forms may be mixed freely in one switch.

  5. Question 5

    This is a switch statement (not an expression) written with arrow labels, and it has no default. What is printed? ```java public class Main { public static void main(String[] args) { StringBuilder out = new StringBuilder(); int n = 2; switch (n) { case 1 -> out.append("one"); case 2 -> out.append("two"); case 3 -> out.append("three"); } System.out.println(out.toString()); } } ```

    1. A. Compilation fails: a switch statement with arrow labels must be exhaustive

      Confuses statements with expressions; only a switch expression (or a pattern switch) must be exhaustive, while a switch statement over an int with no matching label is a legal no-op.

    2. B. twothree

      Carries the colon-label fall-through habit over to arrow labels; an arrow label executes only its own arm — rewriting these as `case 1:`/`case 2:`/`case 3:` really would print twothree, which is why arrow labels exist.

    3. C. twoCorrect answer

      n is 2, so the `case 2 ->` arm appends `two` and control then leaves the switch — arrow labels have no fall-through and need no break — printing two.

    4. D. onetwothree

      Assumes every arm runs, which no form of switch does; the selector still picks a single entry point.

    Explanation

    Trace: n is 2, so the `case 2 ->` arm runs and appends `two`. An arrow label executes only its own arm and then control leaves the switch — there is no fall-through and no `break` is needed. Output is `two`. Why the others are wrong: `twothree` carries the colon-label habit over to arrow labels: it assumes execution keeps running into the following arms until a `break` stops it. Rewriting these three labels as `case 1:`, `case 2:`, `case 3:` really would print `twothree` — that is the whole reason arrow labels exist. `onetwothree` assumes every arm runs, which no form of switch does; the selector still picks a single entry point. `Compilation fails: a switch statement with arrow labels must be exhaustive` confuses statements with expressions. Only a switch *expression* (and a pattern switch) must be exhaustive, because it has to produce a value on every path. A switch *statement* over an `int` with no matching label is a legal no-op. Exam tip: arrow vs colon is about fall-through, not about statement vs expression — you can write a switch statement with either, and a switch expression with either. Ask two separate questions of any switch on the exam: does it produce a value (then it must be exhaustive), and does it use `->` (then no fall-through, no `break`)?

  6. Question 6

    What does this print? ```java public class Main { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); for (int i = 1; i <= 5; i++) { if (i % 2 == 0) { continue; } sb.append(i); } System.out.println(sb); } } ```

    1. A. 12345

      Ignores continue entirely and appends every value, reading the guard as a no-op; continue actually skips the append on even iterations.

    2. B. 24

      Inverts the guard, appending the values continue skips; continue abandons the rest of the body for the values that satisfy the if, it does not select them.

    3. C. 135Correct answer

      Correct: continue abandons the current iteration for i=2 and i=4, skipping the append, so only the odd values 1, 3 and 5 reach it, giving 135.

    4. D. 1

      Treats continue as if it were break, stopping the loop at the first even value after appending only 1; continue keeps the loop going.

    Explanation

    Trace: `continue` abandons the *current iteration only* and jumps to the update part of the for loop (`i++`), then re-tests the condition. So on i = 2 and i = 4 the `sb.append(i)` below the guard is skipped, but the loop keeps going. The odd values 1, 3 and 5 reach the append, giving `135`. Why the others are wrong: `12345` ignores `continue` entirely and appends every value — that is what you get if you read the guard as a no-op. `1` treats `continue` as if it were `break`: the loop would stop dead at the first even value, having appended only 1. `24` inverts the guard, appending the values that `continue` actually skips. `continue` skips the rest of the body for the values that satisfy the `if`, it does not select them. Exam tip: in a `for` loop, `continue` still runs the update expression, so a counter-driven loop cannot be made to spin forever by it. The reverse trap lives in `while`: there the update is usually the last statement of the body, so a `continue` placed above it skips the update and hangs the loop. Exam code that puts `continue` inside a `while` is almost always testing exactly that.

  7. Question 7

    What does this print? ```java public class Main { public static void main(String[] args) { int n = 1; switch (n) { case 1: System.out.print("a"); case 2: System.out.print("b"); break; case 3: System.out.print("c"); } System.out.println(); } } ```

    1. A. a

      This assumes execution stops after the first matching label, but colon labels fall through without a break.

    2. B. abc

      This ignores the `break` after the second label, which prevents reaching the third label's "c".

    3. C. abCorrect answer

      In this colon-form switch statement, `case 1:` prints "a" and, with no break, falls into `case 2:` printing "b"; the `break` there then stops execution before `case 3:`.

    4. D. Compilation fails: case 1 has no break

      A colon `case` without a break is legal; the missing break produces fall-through behaviour, not a compile error.

    Explanation

    In the colon form of a switch statement, control falls through from a matched label into the following labels until a `break` (or other jump) intervenes. The first matched arm has no break, so execution continues into the next arm, whose `break` then halts the switch. A missing `break` is a runtime behaviour in the statement form, not a compile error, and arrow labels would never fall through this way.

  8. Question 8

    What is the result? ```java public class Main { public static void main(String[] args) { String s = "hi"; int len = switch (s) { case "hi" -> { int x = s.length(); yield x * 10; } default -> 0; }; System.out.println(len); } } ```

    1. A. Compilation fails: yield is only allowed inside a loop

      `yield` is exactly the mechanism a block arm uses to produce its value in a switch expression; it has nothing to do with loops.

    2. B. 2

      2 is `s.length()` alone, ignoring the `* 10` applied in the yielded expression.

    3. C. 0

      0 is the `default` arm, which is not selected because "hi" matched the first arm.

    4. D. 20Correct answer

      "hi" selects the block-bodied arm, which computes `x = s.length()` = 2 then `yield x * 10` = 20, the value assigned to `len`.

    Explanation

    A block-bodied arm of a switch expression produces its result with `yield`. The matching arm computes the string length and multiplies it before yielding, and that yielded value becomes the value of the whole switch expression. A bare-expression arrow arm would supply its value directly without the `yield` keyword.

Practise all 16 Switch Expressions & Statements questions

OCP Java SE 25 has the full set, inside timed mock exams that mirror real exam conditions — every question with a worked explanation.

Open OCP Java SE 25

Other topics in this pack