skip to content

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