🔀 Control Flow · Beginner

Labeled break & continue in Java

Exiting nested loops with labels.

🧩 The mysteryYou're searching a grid for treasure. Found it! You break... and the outer loop happily keeps searching the next row. How do you escape both loops at once?

Name your loop

Put a label (a name followed by a colon) in front of a loop. Then **break label;** exits that whole labeled loop, however deeply nested you are.

outer:
for (int r = 0; r < 3; r++) {
    for (int c = 0; c < 3; c++) {
        if (grid[r][c] == 0) break outer;
    }
}
// break outer lands here
🔮 Predict it

Your turn

Which pair is found first?

int found = -1;
search: for (int i = 1; i <= 4; i++) {
    for (int j = 1; j <= 4; j++) {
        if (i * j == 12) {
            found = i * 10 + j;
            break search;
        }
    }
}
System.out.println(found);
  1. 34
  2. 43
  3. -1
  4. 12
Show the answer

Rows are searched in order, so i = 3, j = 4 is the first pair with a product of 12, giving 34. break search then leaves both loops, so 4 x 3 is never reached.

continue with a label

**continue label; abandons the current inner loop and jumps to the next iteration of the labeled loop**. It's like saying "this row is done, next row please".

rows:
for (int r = 0; r < 3; r++) {
    for (int c = 0; c < 3; c++) {
        if (bad(r, c)) continue rows;
        use(r, c);
    }
}
🔮 Predict it

Trace it

What prints?

outer:
for (int r = 0; r < 3; r++) {
    for (int c = 0; c < 3; c++) {
        if (c == 1) continue outer;
        System.out.print(r + "" + c + " ");
    }
}
  1. 00 10 20
  2. 00 01 10 11 20 21
  3. 00
  4. 01 11 21
Show the answer

In every row, as soon as c reaches 1, continue outer abandons the rest of that row and starts the next r. So each row prints only its c = 0 pair.

⚠️ The trap

continue needs a loop

break label; may target any labeled statement, even a plain block. But continue label; must name a loop: a labeled block has no "next iteration". The compiler says not a loop label. And labels aren't goto: you can only jump *out of* statements you're inside.

block: {
    if (done) break block;    // ok
    continue block; // error: not a loop label
}

Escaping two loops

✗ Doesn't work
for (...) {
    for (...) {
        break; break;
    }
}

The first break leaves; the second is unreachable code, so it doesn't even compile.

✓ Works
search:
for (...) {
    for (...) {
        break search;
    }
}

Alternatives without labels: a boolean flag the outer loop checks, or move the loops into a method and return.

💼 In the real world

In real projects

Labels are rare in production code but perfectly legitimate for grid searches and parsers. Many teams prefer moving nested loops into a small method and using return: it's often clearer, and the method name explains what the search does.

Key takeaways

  1. Syntax: outer: for (...) { for (...) { break outer; } }
  2. break label exits the labeled statement completely
  3. continue label must name a loop
  4. Labels aren't goto: you can only jump out of statements you're inside
🤯 Did you know?

A line like http://example.com placed right before a statement in a method compiles! http: is a label, and //example.com is just a comment.

Practice questions

What does this print?

int found = -1;
search: for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 3; j++) {
        if (i * j == 6) {
            found = i * 10 + j;
            break search;
        }
    }
}
System.out.println(found);
  1. 32
  2. -1
  3. 6
  4. 23
Check your answer

23. The first pair with i * j == 6 is i = 2, j = 3, giving 23. break search then leaves both loops, so i = 3, j = 2 is never reached.

Without labels, what's the usual way to stop two nested loops at once?

  1. Write break; break; on the same line
  2. Use continue in the inner loop
  3. Use a boolean flag checked by the outer loop, or move the loops into a method and return
  4. Set the outer loop's variable to null
Check your answer

Use a boolean flag checked by the outer loop, or move the loops into a method and return. A flag or an early return both work. break; break; doesn't: the second break is unreachable code and won't compile.

Next: loops that never end on purpose, and code the compiler refuses to compile because it can never run.