skip to content

Labeled break & continue

Labels let break and continue target an outer loop instead of the innermost one, using label@ and break@label. It is a small feature, but it is the clean answer to the nested-loop early-exit question interviewers pose.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

In a nested for loop, which loop does a plain `break` (without a label) terminate, and how do you instead break out of the outer loop?

level: juniorimportance: must knowfreq 70%

answer

  1. Plain break = innermost loop only
  2. Label syntax: name@ before the loop
  3. break@label / continue@label target outer loop
  4. continue obeys the same innermost-vs-labeled rule
  5. Labels replace boolean-flag workarounds

basics

~10 s

A plain break only stops the loop directly around it (the innermost one). To stop an outer loop, you put a name (label) on that loop and write break@name.

solid answer

~40 s

A plain `break` terminates only the innermost enclosing loop; control resumes right after that loop. To target an outer loop you label it with an identifier followed by `@` (e.g. `outer@ for (...)`) and then use `break@outer`, which exits the loop carrying that label. The same rule applies to `continue`: plain `continue` skips to the next iteration of the innermost loop, while `continue@outer` jumps to the next iteration of the labeled outer loop. Labels in Kotlin are written `name@` before the loop, and referenced as `break@name` / `continue@name`. This avoids the boolean-flag workaround common in Java pre-labels and keeps nested-loop exit explicit and readable.

code

kotlin · 6 lines
kotlin
outer@ for (i in 1..3) {
    for (j in 1..3) {
        if (i * j > 4) break@outer
        println("$i x $j = ${i * j}")
    }
}

go deeper

for a junior

Knows plain break stops only the innermost loop and that a label lets you break an outer one.

for a middle

Writes correct name@ placement and explains continue follows the same rule.

for a senior

Articulates why labels beat boolean flags and notes break/continue are loop-only, distinct from return@.

for a principal

Frames labeled jumps as a readability/intent tool and weighs them against extracting the loop into a function with early return.

## What `break` does by default Kotlin has three structural jump expressions: `break`, `continue`, and `return`. A **plain `break`** (no label) terminates the **nearest enclosing loop** — the loop whose body directly contains it. Execution continues at the first statement after that loop. In nested loops this matters: an inner `break` does NOT escape the outer loop. The outer loop simply continues with its next iteration. ```kotlin for (i in 1..3) { for (j in 1..3) { if (j == 2) break // breaks the INNER loop only println("$i,$j") } } // prints 1,1 2,1 3,1 -> outer loop still runs all 3 times ``` ## Labels: targeting an outer loop A **label** in Kotlin is an identifier followed by `@`, placed immediately before the loop you want to name: ```kotlin outer@ for (i in 1..3) { for (j in 1..3) { if (j == 2) break@outer // exits the OUTER loop entirely println("$i,$j") } } // prints only 1,1 -> the whole nested structure is abandoned ``` - `outer@` declares the label. The name is arbitrary; `loop@`, `rows@`, etc. are all valid. - `break@outer` says "break the loop carrying the label `outer`". ## `continue` follows the same rule - Plain `continue` -> next iteration of the **innermost** loop. - `continue@outer` -> next iteration of the **labeled** loop. ```kotlin outer@ for (i in 1..3) { for (j in 1..3) { if (j == 2) continue@outer // skip rest of inner loop AND advance i println("$i,$j") } } // prints 1,1 2,1 3,1 ``` ## Why this exists Without labels you'd need a boolean flag checked after the inner loop to break the outer one. Labeled jumps make the intent explicit. Note: `break`/`continue` are only valid inside loops (`for`, `while`, `do-while`); they are NOT used to exit a lambda — that uses labeled `return@` (a separate mechanism for the `Returns at Labels` topic).

  • What happens if you write `break` with no label and no enclosing loop?
    It is a compile error — `break` and `continue` are only allowed inside a loop body.
  • Can you put a label on a `while` loop too?
    Yes. Labels work on `for`, `while`, and `do-while` identically — `loop@ while (...) { ... break@loop }`.

A plain break is leaving the room you're standing in; break@building is walking out of the whole building you labeled.

saying these in an interview costs you the question

  • Claiming plain `break` exits all enclosing loops
  • Writing the label after the loop instead of before it
  • Confusing `break@label` (loops) with `return@label` (lambdas)
  • Thinking labels are required even for single loops

context

open as a page

Explain the difference between `continue@outer` and `break@outer` in a nested loop, and trace the output of a short example for each.

level: middleimportance: must knowfreq 55%

basics

~20 s

break@outer quits the named outer loop completely. continue@outer skips the rest of the current inner work and jumps to the outer loop's next iteration. Both target the labeled loop, but one stops it, the other advances it.

open as a page

Where exactly must a loop label be declared in Kotlin, and what are the syntax rules for declaring and referencing it? Show a valid and an invalid placement.

level: middleimportance: should knowfreq 40%

basics

~20 s

Write the label as a name followed by @ directly in front of the loop, like loop@ for (...). To use it, write break@loop or continue@loop with the @ before the name. The label must come before the loop, not after.

open as a page

A candidate tries to use `break` inside a `forEach { }` lambda to stop iteration and it won't compile. Explain why, and what the correct labeled-jump mechanism is in that case versus a real loop.

level: seniorimportance: should knowfreq 45%

basics

~20 s

break and continue only work in real loops (for, while). forEach { } is a function taking a lambda, not a loop, so break won't compile there. Inside the lambda you can only return@forEach to skip the current item, which is like continue, not break.

open as a page

Labeled break/continue can express any nested-loop exit, but is it always the best choice? Discuss the trade-offs and the main alternative for escaping nested loops in Kotlin.

level: seniorimportance: should knowfreq 30%

basics

~20 s

Labels work, but deeply nested labeled jumps get hard to read. Often it's cleaner to pull the nested loops into their own function and use a normal return to exit everything at once, or use a collection operation like firstOrNull.

open as a page